<commit_before>extern crate rand;
extern crate time;
extern crate columnar;
extern crate timely;
extern crate differential_dataflow;

extern crate docopt;
use docopt::Docopt;

use std::thread;
use std::fs::File;
use std::io::{BufRead, BufReader};

use timely::example_shared::*;
use timely::example_shared::operators::*;
use timely::communication::*;
use timely::networking::initialize_networking;
use timely::networking::initialize_networking_from_file;

use timely::drain::DrainExt;

// use differential_dataflow::collection_trace::lookup::UnsignedInt;
// use differential_dataflow::collection_trace::LeastUpperBound;

use differential_dataflow::operators::*;

// The typical differential dataflow vertex receives updates of the form (key, time, value, update),
// where the data are logically partitioned by key, and are then subject to various aggregations by time,
// accumulating for each value the update integers. The resulting multiset is the subjected to computation.

// The implementation I am currently most comfortable with is *conservative* in the sense that it will defer updates
// until it has received all updates for a time, at which point it commits these updates permanently. This is done
// to avoid issues with running logic on partially formed data, but should also simplify our data management story.
// Rather than requiring random access to diffs, we can store them as flat arrays (possibly sorted) and integrate
// them using merge techniques. Updating cached accumulations seems maybe harder w/o hashmaps, but we'll see...

static USAGE: &'static str = "
Usage: tpch17 [options] [<arguments>...]

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
    -h <arg>, --hosts <arg>      list of host:port for workers
";

fn main() {

    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Starting timely with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");

        let hosts = args.get_str("-h");
        let communicators = if hosts != "" {
            initialize_networking_from_file(hosts, process_id, workers).ok().expect("error initializing networking")
        }
        else {
            let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
            initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking")
        };

        start_main(communicators);
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        start_main(ProcessCommunicator::new_vector(workers));
    }
    else {
        println!("Initializing ThreadCommunicator");
        start_main(vec![ThreadCommunicator]);
    };
}

fn start_main<C: Communicator+Send>(communicators: Vec<C>) {
    // let communicators = ProcessCommunicator::new_vector(1);
    let mut guards = Vec::new();
    for communicator in communicators.into_iter() {
        guards.push(thread::Builder::new().name(format!("worker thread {}", communicator.index()))
                                          .spawn(move || test_dataflow(communicator))
                                          .unwrap());
    }

    for guard in guards { guard.join().unwrap(); }
}

fn test_dataflow<C: Communicator>(communicator: C) {

    let start = time::precise_time_s();
    let mut computation = GraphRoot::new(communicator);

    let (mut parts, mut items) = computation.subcomputation(|builder| {

        let (part_input, parts) = builder.new_input::<((u32, String, String), i32)>();
        let (item_input, items) = builder.new_input::<((u32, u32, u64), i32)>();

        // compute the average quantities
        let average = items.group_by_u(|(x,y,_)| (x,y), |k,v| (*k,*v), |_,s,t| {
            let mut sum = 0;
            let mut cnt = 0;
            for &(val,wgt) in s.iter() {
                cnt += wgt;
                sum += val;
            }
            t.push((sum / cnt as u32, 1));
        });

        // filter parts by brand and container
        let parts = parts.filter(|x| (x.0).1 == "Brand#33" && (x.0).2 == "WRAP PACK")
                         .map(|((key, _, _), wgt)| (key, wgt));

        // join items against their averages, filter by quantity, remove filter coordinate
        let items = items.join_u(&average, |x| (x.0, (x.1, x.2)), |y| y, |k, x, f| (*k, x.0, x.1, *f))
                         .filter(|&((_, q, _, avg),_)| q < avg / 5)
                         .map(|((key,_,price,_), wgt)| ((key,price), wgt));

        // semi-join against the part keys we retained. think of a better way to produce sum ...
        parts.join_u(&items, |k| (k,()), |(k,p)| (k,p), |_,_,p| *p)
             .inspect_batch(|_t,x| println!("results: {:?}", x.len()));

        (part_input, item_input)
    });

    let mut parts_buffer = Vec::new();
    let parts_reader =  BufReader::new(File::open(format!("/Users/mcsherry/Desktop/tpch-sf-10/part-{}.tbl", computation.index())).unwrap());
    for line in parts_reader.lines() {
        let text = line.ok().expect("read error");
        let mut fields = text.split("|");

        let part_id = fields.next().unwrap().parse::<u32>().unwrap();
        fields.next();
        fields.next();
        let brand = fields.next().unwrap().to_owned();
        fields.next();
        fields.next();
        let container = fields.next().unwrap().to_owned();

        parts_buffer.push(((part_id, brand, container), 1));
        if parts_buffer.len() == 1024 {
            parts.send_at(0u64, parts_buffer.drain_temp());
            computation.step();

        }
    }

    parts.send_at(0u64, parts_buffer.drain_temp());
    computation.step();

    let mut items_buffer = Vec::new();
    let items_reader =  BufReader::new(File::open(format!("/Users/mcsherry/Desktop/tpch-sf-10/lineitem-{}.tbl", computation.index())).unwrap());
    for line in items_reader.lines() {
        let text = line.ok().expect("read error");
        let mut fields = text.split("|");

        fields.next();
        let item_id = fields.next().unwrap().parse::<u32>().unwrap();
        fields.next();
        fields.next();
        let quantity = fields.next().unwrap().parse::<u32>().unwrap();
        let extended_price = fields.next().unwrap().parse::<f64>().unwrap() as u64;

        items_buffer.push(((item_id, quantity, extended_price), 1));
        if items_buffer.len() == 1024 {
            items.send_at(0u64, items_buffer.drain_temp());
            computation.step();
        }
    }

    items.send_at(0u64, items_buffer.drain_temp());
    computation.step();

    println!("data loaded at {}", time::precise_time_s() - start);

    parts.close();
    items.close();

    while computation.step() { std::thread::yield_now(); }
    computation.step(); // shut down

    println!("computation finished at {}", time::precise_time_s() - start);
}
<commit_msg>updated input parsing<commit_after>extern crate rand;
extern crate time;
extern crate columnar;
extern crate timely;
extern crate differential_dataflow;

extern crate docopt;
use docopt::Docopt;

use std::thread;
use std::fs::File;
use std::io::{BufRead, BufReader};

use timely::example_shared::*;
use timely::example_shared::operators::*;
use timely::communication::*;
use timely::networking::initialize_networking;
use timely::networking::initialize_networking_from_file;

use timely::drain::DrainExt;

// use differential_dataflow::collection_trace::lookup::UnsignedInt;
// use differential_dataflow::collection_trace::LeastUpperBound;

use differential_dataflow::operators::*;

// The typical differential dataflow vertex receives updates of the form (key, time, value, update),
// where the data are logically partitioned by key, and are then subject to various aggregations by time,
// accumulating for each value the update integers. The resulting multiset is the subjected to computation.

// The implementation I am currently most comfortable with is *conservative* in the sense that it will defer updates
// until it has received all updates for a time, at which point it commits these updates permanently. This is done
// to avoid issues with running logic on partially formed data, but should also simplify our data management story.
// Rather than requiring random access to diffs, we can store them as flat arrays (possibly sorted) and integrate
// them using merge techniques. Updating cached accumulations seems maybe harder w/o hashmaps, but we'll see...

static USAGE: &'static str = "
Usage: tpch17 [options] [<arguments>...] <parts> <items>

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
    -h <arg>, --hosts <arg>      list of host:port for workers
";

fn main() {

    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Starting timely with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    let parts_file = args.get_str("<parts>").to_owned();
    let items_file = args.get_str("<items>").to_owned();

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");

        let hosts = args.get_str("-h");
        let communicators = if hosts != "" {
            initialize_networking_from_file(hosts, process_id, workers).ok().expect("error initializing networking")
        }
        else {
            let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
            initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking")
        };

        start_main(communicators, parts_file, items_file);
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        start_main(ProcessCommunicator::new_vector(workers), parts_file, items_file);
    }
    else {
        println!("Initializing ThreadCommunicator");
        start_main(vec![ThreadCommunicator], parts_file, items_file);
    };
}

fn start_main<C: Communicator+Send>(communicators: Vec<C>, parts_pattern: String, items_pattern: String) {
    // let communicators = ProcessCommunicator::new_vector(1);
    let mut guards = Vec::new();
    for communicator in communicators.into_iter() {
        let parts = parts_pattern.clone();
        let items = items_pattern.clone();
        guards.push(thread::Builder::new().name(format!("worker thread {}", communicator.index()))
                                          .spawn(move || test_dataflow(communicator, parts, items))
                                          .unwrap());
    }

    for guard in guards { guard.join().unwrap(); }
}

fn test_dataflow<C: Communicator>(communicator: C, parts_pattern: String, items_pattern: String) {

    let start = time::precise_time_s();
    let mut computation = GraphRoot::new(communicator);

    let (mut parts, mut items) = computation.subcomputation(|builder| {

        let (part_input, parts) = builder.new_input::<((u32, String, String), i32)>();
        let (item_input, items) = builder.new_input::<((u32, u32, u64), i32)>();

        // compute the average quantities
        let average = items.group_by_u(|(x,y,_)| (x,y), |k,v| (*k,*v), |_,s,t| {
            let mut sum = 0;
            let mut cnt = 0;
            for &(val,wgt) in s.iter() {
                cnt += wgt;
                sum += val;
            }
            t.push((sum / cnt as u32, 1));
        });

        // filter parts by brand and container
        let parts = parts.filter(|x| (x.0).1 == "Brand#33" && (x.0).2 == "WRAP PACK")
                         .map(|((key, _, _), wgt)| (key, wgt));

        // join items against their averages, filter by quantity, remove filter coordinate
        let items = items.join_u(&average, |x| (x.0, (x.1, x.2)), |y| y, |k, x, f| (*k, x.0, x.1, *f))
                         .filter(|&((_, q, _, avg),_)| q < avg / 5)
                         .map(|((key,_,price,_), wgt)| ((key,price), wgt));

        // semi-join against the part keys we retained. think of a better way to produce sum ...
        parts.join_u(&items, |k| (k,()), |(k,p)| (k,p), |_,_,p| *p)
             .inspect_batch(|_t,x| println!("results: {:?}", x.len()));

        (part_input, item_input)
    });

    if let Ok(parts_file) = File::open(format!("{}-{}", parts_pattern, computation.index())) {

        let mut parts_buffer = Vec::new();
        let parts_reader = BufReader::new(parts_file);

        for line in parts_reader.lines() {
            let text = line.ok().expect("read error");
            let mut fields = text.split(" ");

            let part_id = fields.next().unwrap().parse::<u32>().unwrap();
            fields.next();
            fields.next();
            let brand = fields.next().unwrap().to_owned();
            fields.next();
            fields.next();
            let container = fields.next().unwrap().to_owned();

            parts_buffer.push(((part_id, brand, container), 1));
            if parts_buffer.len() == 1024 {
                parts.send_at(0u64, parts_buffer.drain_temp());
                computation.step();

            }
        }

        parts.send_at(0u64, parts_buffer.drain_temp());
        computation.step();
    }
    else { println!("worker {}: did not find input {}-{}", computation.index(), parts_pattern, computation.index()); }

    if let Ok(items_file) = File::open(format!("{}-{}", items_pattern, computation.index())) {
        let mut items_buffer = Vec::new();
        let items_reader =  BufReader::new(items_file);
        for line in items_reader.lines() {
            let text = line.ok().expect("read error");
            let mut fields = text.split(" ");

            fields.next();
            let item_id = fields.next().unwrap().parse::<u32>().unwrap();
            fields.next();
            fields.next();
            let quantity = fields.next().unwrap().parse::<u32>().unwrap();
            let extended_price = fields.next().unwrap().parse::<f64>().unwrap() as u64;

            items_buffer.push(((item_id, quantity, extended_price), 1));
            if items_buffer.len() == 1024 {
                items.send_at(0u64, items_buffer.drain_temp());
                computation.step();
            }
        }

        items.send_at(0u64, items_buffer.drain_temp());
        computation.step();
    }
    else { println!("worker {}: did not find input {}-{}", computation.index(), items_pattern, computation.index()); }

    println!("data loaded at {}", time::precise_time_s() - start);

    parts.close();
    items.close();

    while computation.step() { std::thread::yield_now(); }
    computation.step(); // shut down

    println!("computation finished at {}", time::precise_time_s() - start);
}
<|endoftext|>


<commit_before>extern crate glutin;

mod support;

fn main() {
    let events_loop = glutin::winit::EventsLoop::new();
    let window = glutin::winit::WindowBuilder::new()
        .with_title("A fantastic window!")
        .build(&events_loop)
        .unwrap();
    let context = glutin::ContextBuilder::new()
        .build(&window)
        .unwrap();

    let _ = unsafe { context.make_current() };

    println!("Pixel format of the window's GL context: {:?}", context.get_pixel_format());

    let gl = support::load(&context);

                gl.draw_frame((0.0, 1.0, 0.0, 1.0));
                let _ = context.swap_buffers();

    events_loop.run_forever(|event| {
        println!("{:?}", event);

        gl.draw_frame((0.0, 1.0, 0.0, 1.0));
        let _ = context.swap_buffers();

        match event {
            glutin::winit::Event::WindowEvent { event, .. } => match event {
                glutin::winit::WindowEvent::Closed => events_loop.interrupt(),
                glutin::winit::WindowEvent::Resized(w, h) => context.resize(w, h),
                _ => (),
            },
            _ => ()
        }
    });
}
<commit_msg>Remove unnecessary draw from window example (originally for testing wayland)<commit_after>extern crate glutin;

mod support;

fn main() {
    let events_loop = glutin::winit::EventsLoop::new();
    let window = glutin::winit::WindowBuilder::new()
        .with_title("A fantastic window!")
        .build(&events_loop)
        .unwrap();
    let context = glutin::ContextBuilder::new()
        .build(&window)
        .unwrap();

    let _ = unsafe { context.make_current() };

    println!("Pixel format of the window's GL context: {:?}", context.get_pixel_format());

    let gl = support::load(&context);

    events_loop.run_forever(|event| {
        println!("{:?}", event);

        gl.draw_frame((0.0, 1.0, 0.0, 1.0));
        let _ = context.swap_buffers();

        match event {
            glutin::winit::Event::WindowEvent { event, .. } => match event {
                glutin::winit::WindowEvent::Closed => events_loop.interrupt(),
                glutin::winit::WindowEvent::Resized(w, h) => context.resize(w, h),
                _ => (),
            },
            _ => ()
        }
    });
}
<|endoftext|>


<commit_before>use bson::{Bson, Document};
use mongodb::client::coll::options::WriteModel;
use mongodb::client::MongoClient;

#[test]
fn bulk_ordered_insert_only() {
    let client = MongoClient::new("localhost", 27017).unwrap();
    let db = client.db("test");
    let coll = db.collection("bulk_ordered_insert_only");

    coll.drop().unwrap();

    let models = (1..5).map(|i| WriteModel::InsertOne { document: doc! {
        "_id" => (i),
        "x" => (i * 11)
    }}).collect();

    coll.bulk_write(models, true);

    let cursor : Vec<_> = coll.find(None, None).unwrap().collect();

    assert_eq!(cursor.len(), 4);

    for (i, result) in cursor.into_iter().enumerate() {
        let doc = result.unwrap();
        let i = i + 1;

        match doc.get("_id") {
            Some(&Bson::I32(j)) => assert_eq!(i as i32, j),
            _ => panic!("Invalid id: {:?}", doc)
        }

        match doc.get("x") {
            Some(&Bson::I32(j)) => assert_eq!(11 * i as i32, j),
            _ => panic!("Invalid id: {:?}", doc)
        }
    }
}

#[test]
fn bulk_unordered_insert_only() {
    let client = MongoClient::new("localhost", 27017).unwrap();
    let db = client.db("test");
    let coll = db.collection("bulk_unordered_insert_only");

    coll.drop().unwrap();

    let models = (1..5).map(|i| WriteModel::InsertOne { document: doc! {
        "_id" => (i),
        "x" => (i * 11)
    }}).collect();

    coll.bulk_write(models, false);

    let cursor : Vec<_> = coll.find(None, None).unwrap().collect();

    assert_eq!(cursor.len(), 4);

    for (i, result) in cursor.into_iter().enumerate() {
        let doc = result.unwrap();
        let i = i + 1;

        match doc.get("_id") {
            Some(&Bson::I32(j)) => assert_eq!(i as i32, j),
            _ => panic!("Invalid id: {:?}", doc)
        }

        match doc.get("x") {
            Some(&Bson::I32(j)) => assert_eq!(11 * i as i32, j),
            _ => panic!("Invalid id: {:?}", doc)
        }
    }
}
<commit_msg>changed variable name to be more descriptive<commit_after>use bson::{Bson, Document};
use mongodb::client::coll::options::WriteModel;
use mongodb::client::MongoClient;

#[test]
fn bulk_ordered_insert_only() {
    let client = MongoClient::new("localhost", 27017).unwrap();
    let db = client.db("test");
    let coll = db.collection("bulk_ordered_insert_only");

    coll.drop().unwrap();

    let models = (1..5).map(|i| WriteModel::InsertOne { document: doc! {
        "_id" => (i),
        "x" => (i * 11)
    }}).collect();

    coll.bulk_write(models, true);

    let cursor : Vec<_> = coll.find(None, None).unwrap().collect();

    assert_eq!(cursor.len(), 4);

    for (i, result) in cursor.into_iter().enumerate() {
        let doc = result.unwrap();
        let expected_id = i + 1;

        match doc.get("_id") {
            Some(&Bson::I32(j)) => assert_eq!(expected_id as i32, j),
            _ => panic!("Invalid id: {:?}", doc)
        }

        match doc.get("x") {
            Some(&Bson::I32(j)) => assert_eq!(11 * expected_id as i32, j),
            _ => panic!("Invalid id: {:?}", doc)
        }
    }
}

#[test]
fn bulk_unordered_insert_only() {
    let client = MongoClient::new("localhost", 27017).unwrap();
    let db = client.db("test");
    let coll = db.collection("bulk_unordered_insert_only");

    coll.drop().unwrap();

    let models = (1..5).map(|i| WriteModel::InsertOne { document: doc! {
        "_id" => (i),
        "x" => (i * 11)
    }}).collect();

    coll.bulk_write(models, false);

    let cursor : Vec<_> = coll.find(None, None).unwrap().collect();

    assert_eq!(cursor.len(), 4);

    for (i, result) in cursor.into_iter().enumerate() {
        let doc = result.unwrap();
        let i = i + 1;

        match doc.get("_id") {
            Some(&Bson::I32(j)) => assert_eq!(i as i32, j),
            _ => panic!("Invalid id: {:?}", doc)
        }

        match doc.get("x") {
            Some(&Bson::I32(j)) => assert_eq!(11 * i as i32, j),
            _ => panic!("Invalid id: {:?}", doc)
        }
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate tempdir;

use std::env;
use std::fs::{self, File};
use std::io::{Read, Write, Result};
#[cfg(unix)]
use std::os::unix::fs::symlink as symlink_file;
#[cfg(windows)]
use std::os::windows::fs::symlink_file;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::str::from_utf8;
use std::ffi::OsStr;
use self::tempdir::TempDir;
use std::rc::Rc;

#[cfg(windows)]
static PROGNAME: &'static str = "target\\debug\\uutils.exe";
#[cfg(windows)]
static FIXTURES_DIR: &'static str = "tests\\fixtures";
#[cfg(not(windows))]
static PROGNAME: &'static str = "target/debug/uutils";
#[cfg(not(windows))]
static FIXTURES_DIR: &'static str = "tests/fixtures";
static ALREADY_RUN: &'static str = " you have already run this UCommand, if you want to run \
                                    another command in the same test, use TestSet::new instead of \
                                    testing();";

#[macro_export]
macro_rules! assert_empty_stderr(
    ($cond:expr) => (
        if $cond.stderr.len() > 0 {
            panic!(format!("stderr: {}", $cond.stderr))
        }
    );
);

#[macro_export]
macro_rules! assert_no_error(
    ($cond:expr) => (
        assert!($cond.success);
        if $cond.stderr.len() > 0 {
            panic!(format!("stderr: {}", $cond.stderr))
        }
    );
);

pub struct CmdResult {
    pub success: bool,
    pub stdout: String,
    pub stderr: String,
}

pub fn log_info<T: AsRef<str>, U: AsRef<str>>(msg: T, par: U) {
    println!("{}: {}", msg.as_ref(), par.as_ref());
}

pub fn repeat_str(s: &str, n: u32) -> String {
    let mut repeated = String::new();
    for _ in 0..n {
        repeated.push_str(s);
    }
    repeated
}

pub fn recursive_copy(src: &Path, dest: &Path) -> Result<()> {
    if try!(fs::metadata(src)).is_dir() {
        for entry in try!(fs::read_dir(src)) {
            let entry = try!(entry);
            let mut new_dest = PathBuf::from(dest);
            new_dest.push(entry.file_name());
            if try!(fs::metadata(entry.path())).is_dir() {
                try!(fs::create_dir(&new_dest));
                try!(recursive_copy(&entry.path(), &new_dest));
            } else {
                try!(fs::copy(&entry.path(), new_dest));
            }
        }
    }
    Ok(())
}

pub struct AtPath {
    pub subdir: PathBuf,
}
impl AtPath {
    pub fn new(subdir: &Path) -> AtPath {
        AtPath { subdir: PathBuf::from(subdir) }
    }
    pub fn as_string(&self) -> String {
        self.subdir.to_str().unwrap().to_owned()
    }
    pub fn plus(&self, name: &str) -> PathBuf {
        let mut pathbuf = self.subdir.clone();
        pathbuf.push(name);
        pathbuf
    }
    pub fn plus_as_string(&self, name: &str) -> String {
        String::from(self.plus(name).to_str().unwrap())
    }
    fn minus(&self, name: &str) -> PathBuf {
        // relative_from is currently unstable
        let prefixed = PathBuf::from(name);
        if prefixed.starts_with(&self.subdir) {
            let mut unprefixed = PathBuf::new();
            for component in prefixed.components()
                                     .skip(self.subdir.components().count()) {
                unprefixed.push(component.as_ref().to_str().unwrap());
            }
            unprefixed
        } else {
            prefixed
        }
    }
    pub fn minus_as_string(&self, name: &str) -> String {
        String::from(self.minus(name).to_str().unwrap())
    }
    pub fn open(&self, name: &str) -> File {
        log_info("open", self.plus_as_string(name));
        File::open(self.plus(name)).unwrap()
    }
    pub fn read(&self, name: &str) -> String {
        let mut f = self.open(name);
        let mut contents = String::new();
        let _ = f.read_to_string(&mut contents);
        contents
    }
    pub fn write(&self, name: &str, contents: &str) {
        let mut f = self.open(name);
        let _ = f.write(contents.as_bytes());
    }
    pub fn mkdir(&self, dir: &str) {
        log_info("mkdir", self.plus_as_string(dir));
        fs::create_dir(&self.plus(dir)).unwrap();
    }
    pub fn mkdir_all(&self, dir: &str) {
        log_info("mkdir_all", self.plus_as_string(dir));
        fs::create_dir_all(self.plus(dir)).unwrap();
    }
    pub fn make_file(&self, name: &str) -> File {
        match File::create(&self.plus(name)) {
            Ok(f) => f,
            Err(e) => panic!("{}", e),
        }
    }
    pub fn touch(&self, file: &str) {
        log_info("touch", self.plus_as_string(file));
        File::create(&self.plus(file)).unwrap();
    }
    pub fn symlink(&self, src: &str, dst: &str) {
        log_info("symlink",
                 &format!("{},{}", self.plus_as_string(src), self.plus_as_string(dst)));
        symlink_file(&self.plus(src), &self.plus(dst)).unwrap();
    }
    pub fn is_symlink(&self, path: &str) -> bool {
        log_info("is_symlink", self.plus_as_string(path));
        match fs::symlink_metadata(&self.plus(path)) {
            Ok(m) => m.file_type().is_symlink(),
            Err(_) => false,
        }
    }

    pub fn resolve_link(&self, path: &str) -> String {
        log_info("resolve_link", self.plus_as_string(path));
        match fs::read_link(&self.plus(path)) {
            Ok(p) => {
                self.minus_as_string(p.to_str().unwrap())
            }
            Err(_) => "".to_string(),
        }
    }

    pub fn metadata(&self, path: &str) -> fs::Metadata {
        match fs::metadata(&self.plus(path)) {
            Ok(m) => m,
            Err(e) => panic!("{}", e),
        }
    }

    pub fn file_exists(&self, path: &str) -> bool {
        match fs::metadata(&self.plus(path)) {
            Ok(m) => m.is_file(),
            Err(_) => false,
        }
    }

    pub fn dir_exists(&self, path: &str) -> bool {
        match fs::metadata(&self.plus(path)) {
            Ok(m) => m.is_dir(),
            Err(_) => false,
        }
    }

    pub fn cleanup(&self, path: &'static str) {
        let p = &self.plus(path);
        match fs::metadata(p) {
            Ok(m) => if m.is_file() {
                fs::remove_file(&p).unwrap();
            } else {
                fs::remove_dir(&p).unwrap();
            },
            Err(_) => {}
        }
    }

    pub fn root_dir(&self) -> String {
        log_info("current_directory", "");
        self.subdir.to_str().unwrap().to_owned()
    }

    pub fn root_dir_resolved(&self) -> String {
        log_info("current_directory_resolved", "");
        self.subdir.canonicalize().unwrap().to_str().unwrap().to_owned()
    }
}

pub struct TestSet {
    bin_path: PathBuf,
    util_name: String,
    pub fixtures: AtPath,
    tmpd: Rc<TempDir>,
}
impl TestSet {
    pub fn new(util_name: &str) -> TestSet {
        let tmpd = Rc::new(TempDir::new("uutils").unwrap());
        let ts = TestSet {
            bin_path: {
                let mut bin_path_builder = env::current_dir().unwrap();
                bin_path_builder.push(PathBuf::from(PROGNAME));
                bin_path_builder
            },
            util_name: String::from(util_name),
            fixtures: AtPath::new(&tmpd.as_ref().path()),
            tmpd: tmpd,
        };
        let mut fixture_path_builder = env::current_dir().unwrap();
        fixture_path_builder.push(PathBuf::from(FIXTURES_DIR));
        fixture_path_builder.push(PathBuf::from(util_name));
        match fs::metadata(&fixture_path_builder) {
            Ok(m) => if m.is_dir() {
                recursive_copy(&fixture_path_builder, &ts.fixtures.subdir).unwrap();
            },
            Err(_) => {}
        }
        ts
    }
    pub fn util_cmd(&self) -> UCommand {
        let mut cmd = self.cmd(&self.bin_path);
        cmd.arg(&self.util_name);
        cmd
    }
    pub fn cmd<S: AsRef<OsStr>>(&self, bin: S) -> UCommand {
        UCommand::new_from_tmp(bin, self.tmpd.clone(), true)
    }
    // different names are used rather than an argument
    // because the need to keep the environment is exceedingly rare.
    pub fn util_cmd_keepenv(&self) -> UCommand {
        let mut cmd = self.cmd_keepenv(&self.bin_path);
        cmd.arg(&self.util_name);
        cmd
    }
    pub fn cmd_keepenv<S: AsRef<OsStr>>(&self, bin: S) -> UCommand {
        UCommand::new_from_tmp(bin, self.tmpd.clone(), false)
    }
}

pub struct UCommand {
    pub raw: Command,
    comm_string: String,
    tmpd: Option<Rc<TempDir>>,
    has_run: bool,
}
impl UCommand {
    pub fn new<T: AsRef<OsStr>, U: AsRef<OsStr>>(arg: T, curdir: U, env_clear: bool) -> UCommand {
        UCommand {
            tmpd: None,
            has_run: false,
            raw: {
                let mut cmd = Command::new(arg.as_ref());
                cmd.current_dir(curdir.as_ref());
                if env_clear {
                    cmd.env_clear();
                }
                cmd
            },
            comm_string: String::from(arg.as_ref().to_str().unwrap()),
        }
    }
    pub fn new_from_tmp<T: AsRef<OsStr>>(arg: T, tmpd: Rc<TempDir>, env_clear: bool) -> UCommand {
        let tmpd_path_buf = String::from(&(*tmpd.as_ref().path().to_str().unwrap()));
        let mut ucmd: UCommand = UCommand::new(arg.as_ref(), tmpd_path_buf, env_clear);
        ucmd.tmpd = Some(tmpd);
        ucmd
    }
    pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> Box<&mut UCommand> {
        if self.has_run {
            panic!(ALREADY_RUN);
        }
        self.comm_string.push_str(" ");
        self.comm_string.push_str(arg.as_ref().to_str().unwrap());
        self.raw.arg(arg.as_ref());
        Box::new(self)
    }

    pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> Box<&mut UCommand> {
        if self.has_run {
            panic!(ALREADY_RUN);
        }
        for s in args {
            self.comm_string.push_str(" ");
            self.comm_string.push_str(s.as_ref().to_str().unwrap());
        }

        self.raw.args(args.as_ref());
        Box::new(self)
    }

    pub fn env<K, V>(&mut self, key: K, val: V) -> Box<&mut UCommand> where K: AsRef<OsStr>, V: AsRef<OsStr> {
        if self.has_run {
            panic!(ALREADY_RUN);
        }
        self.raw.env(key, val);
        Box::new(self)
    }

    pub fn run(&mut self) -> CmdResult {
        self.has_run = true;
        log_info("run", &self.comm_string);
        let prog = self.raw.output().unwrap();
        CmdResult {
            success: prog.status.success(),
            stdout: from_utf8(&prog.stdout).unwrap().to_string(),
            stderr: from_utf8(&prog.stderr).unwrap().to_string(),
        }
    }
    pub fn run_piped_stdin<T: AsRef<[u8]>>(&mut self, input: T) -> CmdResult {
        self.has_run = true;
        log_info("run_piped_stdin", &self.comm_string);
        let mut result = self.raw
                             .stdin(Stdio::piped())
                             .stdout(Stdio::piped())
                             .stderr(Stdio::piped())
                             .spawn()
                             .unwrap();

        result.stdin
              .take()
              .unwrap_or_else(|| panic!("Could not take child process stdin"))
              .write_all(input.as_ref())
              .unwrap_or_else(|e| panic!("{}", e));

        let prog = result.wait_with_output().unwrap();
        CmdResult {
            success: prog.status.success(),
            stdout: from_utf8(&prog.stdout).unwrap().to_string(),
            stderr: from_utf8(&prog.stderr).unwrap().to_string(),
        }
    }
}

// returns a testSet and a ucommand initialized to the utility binary
// operating in the fixtures directory with a cleared environment
pub fn testset_and_ucommand(utilname: &str) -> (TestSet, UCommand) {
    let ts = TestSet::new(utilname);
    let ucmd = ts.util_cmd();
    (ts, ucmd)
}
pub fn testing(utilname: &str) -> (AtPath, UCommand) {
    let ts = TestSet::new(utilname);
    let ucmd = ts.util_cmd();
    (ts.fixtures, ucmd)
}
<commit_msg>tests: do not remove %SYSTEMROOT% from environment variables, it's required to initialize crypto provider (which is required for std::rand)<commit_after>#![allow(dead_code)]

extern crate tempdir;

use std::env;
use std::fs::{self, File};
use std::io::{Read, Write, Result};
#[cfg(unix)]
use std::os::unix::fs::symlink as symlink_file;
#[cfg(windows)]
use std::os::windows::fs::symlink_file;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::str::from_utf8;
use std::ffi::OsStr;
use self::tempdir::TempDir;
use std::rc::Rc;

#[cfg(windows)]
static PROGNAME: &'static str = "target\\debug\\uutils.exe";
#[cfg(windows)]
static FIXTURES_DIR: &'static str = "tests\\fixtures";
#[cfg(not(windows))]
static PROGNAME: &'static str = "target/debug/uutils";
#[cfg(not(windows))]
static FIXTURES_DIR: &'static str = "tests/fixtures";
static ALREADY_RUN: &'static str = " you have already run this UCommand, if you want to run \
                                    another command in the same test, use TestSet::new instead of \
                                    testing();";

#[macro_export]
macro_rules! assert_empty_stderr(
    ($cond:expr) => (
        if $cond.stderr.len() > 0 {
            panic!(format!("stderr: {}", $cond.stderr))
        }
    );
);

#[macro_export]
macro_rules! assert_no_error(
    ($cond:expr) => (
        assert!($cond.success);
        if $cond.stderr.len() > 0 {
            panic!(format!("stderr: {}", $cond.stderr))
        }
    );
);

pub struct CmdResult {
    pub success: bool,
    pub stdout: String,
    pub stderr: String,
}

pub fn log_info<T: AsRef<str>, U: AsRef<str>>(msg: T, par: U) {
    println!("{}: {}", msg.as_ref(), par.as_ref());
}

pub fn repeat_str(s: &str, n: u32) -> String {
    let mut repeated = String::new();
    for _ in 0..n {
        repeated.push_str(s);
    }
    repeated
}

pub fn recursive_copy(src: &Path, dest: &Path) -> Result<()> {
    if try!(fs::metadata(src)).is_dir() {
        for entry in try!(fs::read_dir(src)) {
            let entry = try!(entry);
            let mut new_dest = PathBuf::from(dest);
            new_dest.push(entry.file_name());
            if try!(fs::metadata(entry.path())).is_dir() {
                try!(fs::create_dir(&new_dest));
                try!(recursive_copy(&entry.path(), &new_dest));
            } else {
                try!(fs::copy(&entry.path(), new_dest));
            }
        }
    }
    Ok(())
}

pub struct AtPath {
    pub subdir: PathBuf,
}
impl AtPath {
    pub fn new(subdir: &Path) -> AtPath {
        AtPath { subdir: PathBuf::from(subdir) }
    }
    pub fn as_string(&self) -> String {
        self.subdir.to_str().unwrap().to_owned()
    }
    pub fn plus(&self, name: &str) -> PathBuf {
        let mut pathbuf = self.subdir.clone();
        pathbuf.push(name);
        pathbuf
    }
    pub fn plus_as_string(&self, name: &str) -> String {
        String::from(self.plus(name).to_str().unwrap())
    }
    fn minus(&self, name: &str) -> PathBuf {
        // relative_from is currently unstable
        let prefixed = PathBuf::from(name);
        if prefixed.starts_with(&self.subdir) {
            let mut unprefixed = PathBuf::new();
            for component in prefixed.components()
                                     .skip(self.subdir.components().count()) {
                unprefixed.push(component.as_ref().to_str().unwrap());
            }
            unprefixed
        } else {
            prefixed
        }
    }
    pub fn minus_as_string(&self, name: &str) -> String {
        String::from(self.minus(name).to_str().unwrap())
    }
    pub fn open(&self, name: &str) -> File {
        log_info("open", self.plus_as_string(name));
        File::open(self.plus(name)).unwrap()
    }
    pub fn read(&self, name: &str) -> String {
        let mut f = self.open(name);
        let mut contents = String::new();
        let _ = f.read_to_string(&mut contents);
        contents
    }
    pub fn write(&self, name: &str, contents: &str) {
        let mut f = self.open(name);
        let _ = f.write(contents.as_bytes());
    }
    pub fn mkdir(&self, dir: &str) {
        log_info("mkdir", self.plus_as_string(dir));
        fs::create_dir(&self.plus(dir)).unwrap();
    }
    pub fn mkdir_all(&self, dir: &str) {
        log_info("mkdir_all", self.plus_as_string(dir));
        fs::create_dir_all(self.plus(dir)).unwrap();
    }
    pub fn make_file(&self, name: &str) -> File {
        match File::create(&self.plus(name)) {
            Ok(f) => f,
            Err(e) => panic!("{}", e),
        }
    }
    pub fn touch(&self, file: &str) {
        log_info("touch", self.plus_as_string(file));
        File::create(&self.plus(file)).unwrap();
    }
    pub fn symlink(&self, src: &str, dst: &str) {
        log_info("symlink",
                 &format!("{},{}", self.plus_as_string(src), self.plus_as_string(dst)));
        symlink_file(&self.plus(src), &self.plus(dst)).unwrap();
    }
    pub fn is_symlink(&self, path: &str) -> bool {
        log_info("is_symlink", self.plus_as_string(path));
        match fs::symlink_metadata(&self.plus(path)) {
            Ok(m) => m.file_type().is_symlink(),
            Err(_) => false,
        }
    }

    pub fn resolve_link(&self, path: &str) -> String {
        log_info("resolve_link", self.plus_as_string(path));
        match fs::read_link(&self.plus(path)) {
            Ok(p) => {
                self.minus_as_string(p.to_str().unwrap())
            }
            Err(_) => "".to_string(),
        }
    }

    pub fn metadata(&self, path: &str) -> fs::Metadata {
        match fs::metadata(&self.plus(path)) {
            Ok(m) => m,
            Err(e) => panic!("{}", e),
        }
    }

    pub fn file_exists(&self, path: &str) -> bool {
        match fs::metadata(&self.plus(path)) {
            Ok(m) => m.is_file(),
            Err(_) => false,
        }
    }

    pub fn dir_exists(&self, path: &str) -> bool {
        match fs::metadata(&self.plus(path)) {
            Ok(m) => m.is_dir(),
            Err(_) => false,
        }
    }

    pub fn cleanup(&self, path: &'static str) {
        let p = &self.plus(path);
        match fs::metadata(p) {
            Ok(m) => if m.is_file() {
                fs::remove_file(&p).unwrap();
            } else {
                fs::remove_dir(&p).unwrap();
            },
            Err(_) => {}
        }
    }

    pub fn root_dir(&self) -> String {
        log_info("current_directory", "");
        self.subdir.to_str().unwrap().to_owned()
    }

    pub fn root_dir_resolved(&self) -> String {
        log_info("current_directory_resolved", "");
        self.subdir.canonicalize().unwrap().to_str().unwrap().to_owned()
    }
}

pub struct TestSet {
    bin_path: PathBuf,
    util_name: String,
    pub fixtures: AtPath,
    tmpd: Rc<TempDir>,
}
impl TestSet {
    pub fn new(util_name: &str) -> TestSet {
        let tmpd = Rc::new(TempDir::new("uutils").unwrap());
        let ts = TestSet {
            bin_path: {
                let mut bin_path_builder = env::current_dir().unwrap();
                bin_path_builder.push(PathBuf::from(PROGNAME));
                bin_path_builder
            },
            util_name: String::from(util_name),
            fixtures: AtPath::new(&tmpd.as_ref().path()),
            tmpd: tmpd,
        };
        let mut fixture_path_builder = env::current_dir().unwrap();
        fixture_path_builder.push(PathBuf::from(FIXTURES_DIR));
        fixture_path_builder.push(PathBuf::from(util_name));
        match fs::metadata(&fixture_path_builder) {
            Ok(m) => if m.is_dir() {
                recursive_copy(&fixture_path_builder, &ts.fixtures.subdir).unwrap();
            },
            Err(_) => {}
        }
        ts
    }
    pub fn util_cmd(&self) -> UCommand {
        let mut cmd = self.cmd(&self.bin_path);
        cmd.arg(&self.util_name);
        cmd
    }
    pub fn cmd<S: AsRef<OsStr>>(&self, bin: S) -> UCommand {
        UCommand::new_from_tmp(bin, self.tmpd.clone(), true)
    }
    // different names are used rather than an argument
    // because the need to keep the environment is exceedingly rare.
    pub fn util_cmd_keepenv(&self) -> UCommand {
        let mut cmd = self.cmd_keepenv(&self.bin_path);
        cmd.arg(&self.util_name);
        cmd
    }
    pub fn cmd_keepenv<S: AsRef<OsStr>>(&self, bin: S) -> UCommand {
        UCommand::new_from_tmp(bin, self.tmpd.clone(), false)
    }
}

pub struct UCommand {
    pub raw: Command,
    comm_string: String,
    tmpd: Option<Rc<TempDir>>,
    has_run: bool,
}
impl UCommand {
    pub fn new<T: AsRef<OsStr>, U: AsRef<OsStr>>(arg: T, curdir: U, env_clear: bool) -> UCommand {
        UCommand {
            tmpd: None,
            has_run: false,
            raw: {
                let mut cmd = Command::new(arg.as_ref());
                cmd.current_dir(curdir.as_ref());
                if env_clear {
                    if cfg!(windows) {
                        // %SYSTEMROOT% is required on Windows to initialize crypto provider
                        // ... and crypto provider is required for std::rand
                        // From procmon: RegQueryValue HKLM\SOFTWARE\Microsoft\Cryptography\Defaults\Provider\Microsoft Strong Cryptographic Provider\Image Path
                        // SUCCESS  Type: REG_SZ, Length: 66, Data: %SystemRoot%\system32\rsaenh.dll"
                        for (key, _) in env::vars_os() {
                            if key.as_os_str() != "SYSTEMROOT" {
                                cmd.env_remove(key);
                            }
                        }
                    } else {
                        cmd.env_clear();
                    }
                }
                cmd
            },
            comm_string: String::from(arg.as_ref().to_str().unwrap()),
        }
    }
    pub fn new_from_tmp<T: AsRef<OsStr>>(arg: T, tmpd: Rc<TempDir>, env_clear: bool) -> UCommand {
        let tmpd_path_buf = String::from(&(*tmpd.as_ref().path().to_str().unwrap()));
        let mut ucmd: UCommand = UCommand::new(arg.as_ref(), tmpd_path_buf, env_clear);
        ucmd.tmpd = Some(tmpd);
        ucmd
    }
    pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> Box<&mut UCommand> {
        if self.has_run {
            panic!(ALREADY_RUN);
        }
        self.comm_string.push_str(" ");
        self.comm_string.push_str(arg.as_ref().to_str().unwrap());
        self.raw.arg(arg.as_ref());
        Box::new(self)
    }

    pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> Box<&mut UCommand> {
        if self.has_run {
            panic!(ALREADY_RUN);
        }
        for s in args {
            self.comm_string.push_str(" ");
            self.comm_string.push_str(s.as_ref().to_str().unwrap());
        }

        self.raw.args(args.as_ref());
        Box::new(self)
    }

    pub fn env<K, V>(&mut self, key: K, val: V) -> Box<&mut UCommand> where K: AsRef<OsStr>, V: AsRef<OsStr> {
        if self.has_run {
            panic!(ALREADY_RUN);
        }
        self.raw.env(key, val);
        Box::new(self)
    }

    pub fn run(&mut self) -> CmdResult {
        self.has_run = true;
        log_info("run", &self.comm_string);
        let prog = self.raw.output().unwrap();
        CmdResult {
            success: prog.status.success(),
            stdout: from_utf8(&prog.stdout).unwrap().to_string(),
            stderr: from_utf8(&prog.stderr).unwrap().to_string(),
        }
    }
    pub fn run_piped_stdin<T: AsRef<[u8]>>(&mut self, input: T) -> CmdResult {
        self.has_run = true;
        log_info("run_piped_stdin", &self.comm_string);
        let mut result = self.raw
                             .stdin(Stdio::piped())
                             .stdout(Stdio::piped())
                             .stderr(Stdio::piped())
                             .spawn()
                             .unwrap();

        result.stdin
              .take()
              .unwrap_or_else(|| panic!("Could not take child process stdin"))
              .write_all(input.as_ref())
              .unwrap_or_else(|e| panic!("{}", e));

        let prog = result.wait_with_output().unwrap();
        CmdResult {
            success: prog.status.success(),
            stdout: from_utf8(&prog.stdout).unwrap().to_string(),
            stderr: from_utf8(&prog.stderr).unwrap().to_string(),
        }
    }
}

// returns a testSet and a ucommand initialized to the utility binary
// operating in the fixtures directory with a cleared environment
pub fn testset_and_ucommand(utilname: &str) -> (TestSet, UCommand) {
    let ts = TestSet::new(utilname);
    let ucmd = ts.util_cmd();
    (ts, ucmd)
}
pub fn testing(utilname: &str) -> (AtPath, UCommand) {
    let ts = TestSet::new(utilname);
    let ucmd = ts.util_cmd();
    (ts.fixtures, ucmd)
}
<|endoftext|>


<commit_before>use std::ops::{Deref, DerefMut};
use std::hash;
use std::fmt;
use std::convert::From;

use combine::primitives::SourcePosition;

/// Struct representing a position within a source code file.
///
/// This represents positions using `i32`s because that's how
/// positions are represented in `combine` (the parsing library
/// that we will use for the Mnemosyne parser). I personally would
/// have used `usize`s...
#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub struct Position { pub col: i32
                    , pub row: i32
                    , pub raw: i32
                    }

impl Position {

    /// Create a new `Position `at the given column and row.
    #[inline]
    pub fn new(col: i32, row: i32) -> Self {
        Position { col: col
                 , row: row
                 , raw: col + row
                 }
    }

}

impl From<SourcePosition> for Position {
    /// Create a new `Position` from a `combine` `SourcePosition`.
    ///
    /// # Example
    /// ```
    /// # extern crate combine;
    /// # extern crate mnemosyne;
    /// # use combine::primitives::SourcePosition;
    /// # use mnemosyne::position::Position;
    /// # fn main() {
    /// let sp = SourcePosition { column: 1, line: 1 };
    /// assert_eq!(Position::from(sp), Position::new(1,1));
    /// # }
    /// ```
    fn from(p: SourcePosition) -> Self { Position::new(p.column, p.line) }
}

impl From<(i32,i32)> for Position {
    /// Create a new `Position` from a tuple of i32s.
    ///
    /// # Example
    /// ```
    /// # use mnemosyne::position::Position;
    /// let tuple: (i32,i32) = (1,1);
    /// assert_eq!(Position::from(tuple), Position::new(1,1));
    /// ```
    fn from((col, row): (i32,i32)) -> Self { Position::new(col,row) }
}

impl fmt::Display for Position {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "line {}, column {}", self.row, self.col)
    }
}

#[derive(Clone, Debug)]
pub struct Positional<T> { pub pos: Position
                         , pub value: T
                         }

impl<T> Positional<T> {
    /// Create a new Positional marker at the given position.
    pub fn at(col: i32, row: i32, value: T) -> Positional<T> {
        Positional { pos: Position::new(col, row)
                   , value: value }
    }

    pub fn value(&self) -> &T { &self.value }
}

impl<T> fmt::Display for Positional<T>
where T: fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} at {}", self.value, self.pos)
    }
}

impl<T> hash::Hash for Positional<T>
where T: hash::Hash {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.value.hash(state)
    }
}

impl<T> PartialEq for Positional<T>
where T: PartialEq {
    fn eq(&self, other: &Positional<T>) -> bool {
        self.value == other.value
    }
}

impl<T> Eq for Positional<T>
where T: Eq
    , T: PartialEq
    {}

impl<T> Deref for Positional<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.value
    }
}

impl<T> DerefMut for Positional<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.value
    }
}
<commit_msg>Added some documentation<commit_after>use std::ops::{Deref, DerefMut};
use std::hash;
use std::fmt;
use std::convert::From;

use combine::primitives::SourcePosition;

/// Struct representing a position within a source code file.
///
/// This represents positions using `i32`s because that's how
/// positions are represented in `combine` (the parsing library
/// that we will use for the Mnemosyne parser). I personally would
/// have used `usize`s...
#[derive(Copy, Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
pub struct Position { pub col: i32
                    , pub row: i32
                    , pub raw: i32
                    }

impl Position {

    /// Create a new `Position `at the given column and row.
    #[inline]
    pub fn new(col: i32, row: i32) -> Self {
        Position { col: col
                 , row: row
                 , raw: col + row
                 }
    }

}

impl From<SourcePosition> for Position {
    /// Create a new `Position` from a `combine` `SourcePosition`.
    ///
    /// # Example
    /// ```
    /// # extern crate combine;
    /// # extern crate mnemosyne;
    /// # use combine::primitives::SourcePosition;
    /// # use mnemosyne::position::Position;
    /// # fn main() {
    /// let sp = SourcePosition { column: 1, line: 1 };
    /// assert_eq!(Position::from(sp), Position::new(1,1));
    /// # }
    /// ```
    fn from(p: SourcePosition) -> Self { Position::new(p.column, p.line) }
}

impl From<(i32,i32)> for Position {
    /// Create a new `Position` from a tuple of i32s.
    ///
    /// # Example
    /// ```
    /// # use mnemosyne::position::Position;
    /// let tuple: (i32,i32) = (1,1);
    /// assert_eq!(Position::from(tuple), Position::new(1,1));
    /// ```
    fn from((col, row): (i32,i32)) -> Self { Position::new(col,row) }
}

impl fmt::Display for Position {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "line {}, column {}", self.row, self.col)
    }
}

#[derive(Clone, Debug)]
pub struct Positional<T> { pub pos: Position
                         , pub value: T
                         }

impl<T> Positional<T> {
    /// Create a new Positional marker at the given position.
    pub fn at(col: i32, row: i32, value: T) -> Positional<T> {
        Positional { pos: Position::new(col, row)
                   , value: value }
    }

    pub fn value(&self) -> &T { &self.value }
}

impl<T> fmt::Display for Positional<T>
where T: fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} at {}", self.value, self.pos)
    }
}

/// A positional pointer is still equal to the underlying
/// value even if they have different positions. This is
/// important so that we can test that two identifiers are
/// the same.
impl<T> PartialEq for Positional<T>
where T: PartialEq {
    fn eq(&self, other: &Positional<T>) -> bool {
        self.value == other.value
    }
}

/// If two things are equal, then they better have the same
/// hash as well. Otherwise there will be sadness.
impl<T> hash::Hash for Positional<T>
where T: hash::Hash {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.value.hash(state)
    }
}

/// This is literally just waving my hands for the compiler.
///
/// Hopefully it understands what I mean.
impl<T> Eq for Positional<T>
where T: Eq
    , T: PartialEq
    {}

impl<T> Deref for Positional<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.value
    }
}

impl<T> DerefMut for Positional<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.value
    }
}
<|endoftext|>


<commit_before>//! The integration suite helpers.

use regex::Regex;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::collections::HashMap;
use std::str::FromStr;
use std::thread::sleep;
use std::time::Duration;

/// List windows will give details about the active sessions in testing.
/// target: A string represented by the {named_session}:{named_window}
/// tmux list-windows -t TARGET -F '#{window_index}: #{window_name}#{?window_active,*, } (#{window_panes} panes) (Dir: #{pane_current_path}) (Session: #{session_name})'
pub fn list_windows(target: &String) -> String {
    let output = Command::new("tmux")
                     .arg("list-windows")
                     .arg("-t")
                     .arg(target)
                     .arg("-F")
                     .arg("'#{window_index}: #{window_name}#{?window_active,*, } (#{window_panes} panes) (Dir: #{pane_current_path}) (Session: #{session_name})'")
                     .output()
                     .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    String::from_utf8_lossy(&output.stdout).into_owned()
}

pub fn open_muxed(project: &String, project_root: &Path) -> () {
    println!("root: {}", project_root.display());
    let output = Command::new("./target/debug/muxed")
        .arg("-d")
        .arg("-p")
        .arg(format!("{}", project_root.display()))
        .arg(project)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    println!("status: {}", output.status);
    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
}

pub fn kill_session(target: &str) -> () {
    Command::new("tmux")
        .arg("kill-session")
        .arg("-t")
        .arg(target)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
}

pub fn send_keys(target: &String, exec: &String) -> () {
    Command::new("tmux")
        .arg("send-keys")
        .arg("-t")
        .arg(target)
        .arg(exec)
        .arg("KPEnter")
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
}

pub fn wait_on(file: &PathBuf) -> () {
    while !file.exists() {
        // Wait increased from 10 to 750 due to the pre_window tests.
        sleep(Duration::from_millis(750));
    }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum SessionValue {
    Usize(usize),
    String(String),
    Empty,
}

impl SessionValue {
    pub fn as_str(&self) -> Option<&str> {
        match self {
            &SessionValue::String(ref s) => Some(s),
            _ => None
        }
    }

    pub fn as_usize(&self) -> Option<usize> {
        match self {
            &SessionValue::Usize(s) => Some(s),
            _ => None
        }
    }
}

#[derive(Debug)]
pub struct TmuxSession {
    pub num_of_windows: usize,
    pub windows: HashMap<String, WindowValues>,
    pub window_active: SessionValue,
    pub name: SessionValue,
}

#[derive(Debug, Clone)]
pub struct WindowValues {
    pub panes: SessionValue,
    pub pane_current_path: SessionValue,
}

static NAME_REGEX:              &'static str = r"\(Session: (.*)\)";
static WINDOW_NAME_REGEX:       &'static str = r":\s(\w*)[$\*-]?\s+\(";
static WINDOW_ACTIVE_REGEX:     &'static str = r"\s(.*)\*";
static PANE_CURRENT_PATH_REGEX: &'static str = r"\(Dir: (.*)\) ";
static PANES_COUNT_REGEX:       &'static str = r"\((\d*) panes\)";

impl TmuxSession {
    pub fn from_string(results: &str) -> TmuxSession {
        let window_name = Regex::new(WINDOW_NAME_REGEX).unwrap();

        let lines: Vec<&str> = results.split("\n").collect();
        let (_, window_lines) = lines.split_last().unwrap();

        let mut windows: HashMap<String, WindowValues> = HashMap::new();

        for line in window_lines {
            let cap = window_name.captures(line).unwrap();
            let name = cap.get(1).unwrap().as_str();

            let win_val = WindowValues{
                panes: TmuxSession::count_panes(line),
                pane_current_path: TmuxSession::retrieve_capture(line, PANE_CURRENT_PATH_REGEX).unwrap_or(SessionValue::Empty)
            };

            windows.insert(name.to_string(), win_val.clone());
        }

        TmuxSession {
          num_of_windows: window_lines.len(),
          windows: windows,
          window_active: TmuxSession::retrieve_capture(window_lines[0], WINDOW_ACTIVE_REGEX).unwrap_or(SessionValue::Empty),
          name: TmuxSession::retrieve_capture(window_lines[0], NAME_REGEX).unwrap_or(SessionValue::Empty)
        }
    }

    pub fn retrieve_capture(line: &str, pattern: &str) -> Result<SessionValue, String> {
        let reg = Regex::new(pattern).unwrap();

        if let Some(caps) = reg.captures(line) {
            return match caps.get(1) {
               Some(x) => Ok(SessionValue::String(x.as_str().to_string())),
               None    => Err("No capture".to_string())
            };
        };

        Err("No capture".to_string())
    }

    pub fn count_panes(line: &str) -> SessionValue {
        let panes = Regex::new(PANES_COUNT_REGEX).unwrap();
        let mut num: &str = "";

        for cap in panes.captures_iter(line) {
            num = match cap.get(1) {
                Some(x) => x.as_str(),
                None    => "0"
            }
        }

        SessionValue::Usize(usize::from_str(num).unwrap())
    }
}

#[test]
fn count_panes_returns_two() {
    let num = TmuxSession::count_panes("1: ssh  (2 panes) (Dir: /Projects/muxed) (session: muxed)");
    assert_eq!(num.as_usize().unwrap(), 2)
}

#[test]
fn count_panes_returns_one() {
    let num = TmuxSession::count_panes("1: ssh  (1 panes) (Dir: /Projects/muxed) (session: muxed)");
    assert_eq!(num.as_usize().unwrap(), 1)
}

#[test]
fn parses_with_trailing_whitespace_after_window_name() {
    let config = "1: ssh  (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_previous_flag() {
    let config = "1: ssh- (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_dollar_sign_flag() {
    let config = "1: ssh$ (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_window_flag() {
    let config = "1: ssh* (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn count_three_windows() {
    let config = "1: ssh  (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  2: vim- (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  3: bash* (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let num = TmuxSession::from_string(&config.to_string()).num_of_windows;
    assert_eq!(num, 3)
}

#[test]
fn count_four_total_panes() {
    let config = "1: ssh  (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  2: vim- (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  3: bash* (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let num = session.windows["ssh"].panes.as_usize().unwrap();
    let num1 = session.windows["vim"].panes.as_usize().unwrap();
    let num2 = session.windows["bash"].panes.as_usize().unwrap();
    assert_eq!(num, 1);
    assert_eq!(num1, 1);
    assert_eq!(num2, 2)
}

#[test]
fn expect_ok_session_name_capture() {
    let line = "2: vim1* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, NAME_REGEX);
    assert!(result.is_ok())
}

#[test]
fn expect_err_session_name_capture() {
    let line = "2: vim1* (1 panes) (Dir: /Projects/muxed) (Session:)";
    let result = TmuxSession::retrieve_capture(line, NAME_REGEX);
    assert!(result.is_err())
}

#[test]
fn expect_muxed_to_be_captured_as_session() {
    let line = "2: vim1* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, NAME_REGEX).unwrap();
    assert_eq!(result.as_str().unwrap(), "muxed")
}

#[test]
fn expect_ok_window_name_capture() {
    let line = "2: vim1* (1 panes) vim2* (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_NAME_REGEX);
    assert!(result.is_ok())
}

#[test]
fn expect_err_window_name_capture() {
    let line = "2: (1 panes) vim2* (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_NAME_REGEX);
    assert!(result.is_err())
}

#[test]
fn expect_vim1_window_name_capture() {
    let line = "2: vim1* (1 panes) vim2* (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_NAME_REGEX).unwrap();
    assert_eq!(result.as_str().unwrap(), "vim1")
}

#[test]
fn expect_ok_active_window_capture() {
    let line = "2: vim* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_ACTIVE_REGEX);
    assert!(result.is_ok())
}

#[test]
fn expect_err_active_window_capture() {
    let line = "2: vim (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_ACTIVE_REGEX);
    assert!(result.is_err())
}

#[test]
fn expect_vim_active_window_capture() {
    let line = "2: vim* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_ACTIVE_REGEX).unwrap();
    assert_eq!(result.as_str().unwrap(), "vim")
}
<commit_msg>refactor(tests): Use a character instead of a str<commit_after>//! The integration suite helpers.

use regex::Regex;
use std::process::Command;
use std::path::{Path, PathBuf};
use std::collections::HashMap;
use std::str::FromStr;
use std::thread::sleep;
use std::time::Duration;

/// List windows will give details about the active sessions in testing.
/// target: A string represented by the {named_session}:{named_window}
/// tmux list-windows -t TARGET -F '#{window_index}: #{window_name}#{?window_active,*, } (#{window_panes} panes) (Dir: #{pane_current_path}) (Session: #{session_name})'
pub fn list_windows(target: &String) -> String {
    let output = Command::new("tmux")
                     .arg("list-windows")
                     .arg("-t")
                     .arg(target)
                     .arg("-F")
                     .arg("'#{window_index}: #{window_name}#{?window_active,*, } (#{window_panes} panes) (Dir: #{pane_current_path}) (Session: #{session_name})'")
                     .output()
                     .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    String::from_utf8_lossy(&output.stdout).into_owned()
}

pub fn open_muxed(project: &String, project_root: &Path) -> () {
    println!("root: {}", project_root.display());
    let output = Command::new("./target/debug/muxed")
        .arg("-d")
        .arg("-p")
        .arg(format!("{}", project_root.display()))
        .arg(project)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });

    println!("status: {}", output.status);
    println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
    println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
}

pub fn kill_session(target: &str) -> () {
    Command::new("tmux")
        .arg("kill-session")
        .arg("-t")
        .arg(target)
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
}

pub fn send_keys(target: &String, exec: &String) -> () {
    Command::new("tmux")
        .arg("send-keys")
        .arg("-t")
        .arg(target)
        .arg(exec)
        .arg("KPEnter")
        .output()
        .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
}

pub fn wait_on(file: &PathBuf) -> () {
    while !file.exists() {
        // Wait increased from 10 to 750 due to the pre_window tests.
        sleep(Duration::from_millis(750));
    }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum SessionValue {
    Usize(usize),
    String(String),
    Empty,
}

impl SessionValue {
    pub fn as_str(&self) -> Option<&str> {
        match self {
            &SessionValue::String(ref s) => Some(s),
            _ => None
        }
    }

    pub fn as_usize(&self) -> Option<usize> {
        match self {
            &SessionValue::Usize(s) => Some(s),
            _ => None
        }
    }
}

#[derive(Debug)]
pub struct TmuxSession {
    pub num_of_windows: usize,
    pub windows: HashMap<String, WindowValues>,
    pub window_active: SessionValue,
    pub name: SessionValue,
}

#[derive(Debug, Clone)]
pub struct WindowValues {
    pub panes: SessionValue,
    pub pane_current_path: SessionValue,
}

static NAME_REGEX:              &'static str = r"\(Session: (.*)\)";
static WINDOW_NAME_REGEX:       &'static str = r":\s(\w*)[$\*-]?\s+\(";
static WINDOW_ACTIVE_REGEX:     &'static str = r"\s(.*)\*";
static PANE_CURRENT_PATH_REGEX: &'static str = r"\(Dir: (.*)\) ";
static PANES_COUNT_REGEX:       &'static str = r"\((\d*) panes\)";

impl TmuxSession {
    pub fn from_string(results: &str) -> TmuxSession {
        let window_name = Regex::new(WINDOW_NAME_REGEX).unwrap();

        let lines: Vec<&str> = results.split('\n').collect();
        let (_, window_lines) = lines.split_last().unwrap();

        let mut windows: HashMap<String, WindowValues> = HashMap::new();

        for line in window_lines {
            let cap = window_name.captures(line).unwrap();
            let name = cap.get(1).unwrap().as_str();

            let win_val = WindowValues{
                panes: TmuxSession::count_panes(line),
                pane_current_path: TmuxSession::retrieve_capture(line, PANE_CURRENT_PATH_REGEX).unwrap_or(SessionValue::Empty)
            };

            windows.insert(name.to_string(), win_val.clone());
        }

        TmuxSession {
          num_of_windows: window_lines.len(),
          windows: windows,
          window_active: TmuxSession::retrieve_capture(window_lines[0], WINDOW_ACTIVE_REGEX).unwrap_or(SessionValue::Empty),
          name: TmuxSession::retrieve_capture(window_lines[0], NAME_REGEX).unwrap_or(SessionValue::Empty)
        }
    }

    pub fn retrieve_capture(line: &str, pattern: &str) -> Result<SessionValue, String> {
        let reg = Regex::new(pattern).unwrap();

        if let Some(caps) = reg.captures(line) {
            return match caps.get(1) {
               Some(x) => Ok(SessionValue::String(x.as_str().to_string())),
               None    => Err("No capture".to_string())
            };
        };

        Err("No capture".to_string())
    }

    pub fn count_panes(line: &str) -> SessionValue {
        let panes = Regex::new(PANES_COUNT_REGEX).unwrap();
        let mut num: &str = "";

        for cap in panes.captures_iter(line) {
            num = match cap.get(1) {
                Some(x) => x.as_str(),
                None    => "0"
            }
        }

        SessionValue::Usize(usize::from_str(num).unwrap())
    }
}

#[test]
fn count_panes_returns_two() {
    let num = TmuxSession::count_panes("1: ssh  (2 panes) (Dir: /Projects/muxed) (session: muxed)");
    assert_eq!(num.as_usize().unwrap(), 2)
}

#[test]
fn count_panes_returns_one() {
    let num = TmuxSession::count_panes("1: ssh  (1 panes) (Dir: /Projects/muxed) (session: muxed)");
    assert_eq!(num.as_usize().unwrap(), 1)
}

#[test]
fn parses_with_trailing_whitespace_after_window_name() {
    let config = "1: ssh  (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_previous_flag() {
    let config = "1: ssh- (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_dollar_sign_flag() {
    let config = "1: ssh$ (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn parses_with_window_flag() {
    let config = "1: ssh* (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let panes = session.windows["ssh"].panes.as_usize().unwrap();
    assert_eq!(session.num_of_windows, 1);
    assert_eq!(panes, 2)
}

#[test]
fn count_three_windows() {
    let config = "1: ssh  (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  2: vim- (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  3: bash* (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let num = TmuxSession::from_string(&config.to_string()).num_of_windows;
    assert_eq!(num, 3)
}

#[test]
fn count_four_total_panes() {
    let config = "1: ssh  (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  2: vim- (1 panes) (Dir: /Projects/muxed) (Session: muxed)
                  3: bash* (2 panes) (Dir: /Projects/muxed) (Session: muxed)\n";
    let session = TmuxSession::from_string(&config.to_string());
    let num = session.windows["ssh"].panes.as_usize().unwrap();
    let num1 = session.windows["vim"].panes.as_usize().unwrap();
    let num2 = session.windows["bash"].panes.as_usize().unwrap();
    assert_eq!(num, 1);
    assert_eq!(num1, 1);
    assert_eq!(num2, 2)
}

#[test]
fn expect_ok_session_name_capture() {
    let line = "2: vim1* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, NAME_REGEX);
    assert!(result.is_ok())
}

#[test]
fn expect_err_session_name_capture() {
    let line = "2: vim1* (1 panes) (Dir: /Projects/muxed) (Session:)";
    let result = TmuxSession::retrieve_capture(line, NAME_REGEX);
    assert!(result.is_err())
}

#[test]
fn expect_muxed_to_be_captured_as_session() {
    let line = "2: vim1* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, NAME_REGEX).unwrap();
    assert_eq!(result.as_str().unwrap(), "muxed")
}

#[test]
fn expect_ok_window_name_capture() {
    let line = "2: vim1* (1 panes) vim2* (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_NAME_REGEX);
    assert!(result.is_ok())
}

#[test]
fn expect_err_window_name_capture() {
    let line = "2: (1 panes) vim2* (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_NAME_REGEX);
    assert!(result.is_err())
}

#[test]
fn expect_vim1_window_name_capture() {
    let line = "2: vim1* (1 panes) vim2* (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_NAME_REGEX).unwrap();
    assert_eq!(result.as_str().unwrap(), "vim1")
}

#[test]
fn expect_ok_active_window_capture() {
    let line = "2: vim* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_ACTIVE_REGEX);
    assert!(result.is_ok())
}

#[test]
fn expect_err_active_window_capture() {
    let line = "2: vim (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_ACTIVE_REGEX);
    assert!(result.is_err())
}

#[test]
fn expect_vim_active_window_capture() {
    let line = "2: vim* (1 panes) (Dir: /Projects/muxed) (Session: muxed)";
    let result = TmuxSession::retrieve_capture(line, WINDOW_ACTIVE_REGEX).unwrap();
    assert_eq!(result.as_str().unwrap(), "vim")
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]
extern crate string_telephone;

use string_telephone::{ConnectionConfig, ClientConnectionConfig, Server, Packet, PollEmpty, PacketConnect, PacketMessage, PacketDisconnect, PollDisconnected, Command};
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::time::duration::Duration;
use std::io::net::udp::UdpSocket;
use std::io::Timer;

mod test_shared;

macro_rules! with_bound_socket(
    (($variable:ident)$code:block) => (
        spawn(proc() {
            match UdpSocket::bind(SocketAddr{ ip: Ipv4Addr(0, 0, 0, 0), port: 0 }) {
                Ok(mut $variable) => $code,
                Err(e) => fail!(e)
            }
        });
    )
)

fn generate_settings(port: u16, protocol_id: u32) -> (SocketAddr, ConnectionConfig<Vec<u8>>) {
    let my_addr = SocketAddr{ ip: Ipv4Addr(127, 0, 0, 1), port: port };
    let settings = ConnectionConfig::new(protocol_id, Duration::seconds(10), test_shared::deserializer, test_shared::serializer);
    (my_addr, settings)
}

/**
 * Test we can start listening
 */
#[test]
fn create_server() {
    let socket = 64000;
    let (my_addr, settings) = generate_settings(socket, 121);
    match Server::new(my_addr, settings) {
        Ok(_) => (), //passed
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we get empty polls when we have no clients
 */
#[test]
fn empty_poll() {
    let socket = 64001;
    let (my_addr, settings) = generate_settings(socket, 121);
    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            assert!(server.poll().is_none())
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we reject bad connection attempts
 */
#[test]
fn bad_client_attempt() {
    let socket = 64002;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(122).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx.send(());
            });
            rx.recv();
            Timer::new().unwrap().sleep(Duration::seconds(1));
            assert!(server.poll().is_none())
            assert!(server.all_connections().len() == 0);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can take a single client
 */
#[test]
fn single_client() {
    let socket = 64003;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx.send(());
            });
            rx.recv();
            Timer::new().unwrap().sleep(Duration::seconds(1));
            match server.poll() {
                Some((Command(PacketConnect), _))=> (),
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            }
            assert!(server.all_connections().len() == 1);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can take multiple clients
 */
#[test]
fn multiple_clients() {
    let socket = 64004;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();
    let tx2 = tx.clone();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx.send(());
            });
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx2.send(());
            });
            rx.recv();
            rx.recv();
            Timer::new().unwrap().sleep(Duration::seconds(1));
            match server.poll() {
                Some((Command(PacketConnect), _))=> (),
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            };
            match server.poll() {
                Some((Command(PacketConnect), _))=> (),
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            }
            assert!(server.all_connections().len() == 2);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can cull old clients
 */
#[test]
fn cull() {
    let socket = 64005;
    let (my_addr, mut settings) = generate_settings(socket, 121);
    settings.timeout_period = Duration::seconds(0);
    let (tx, rx) = channel();
    let tx2 = tx.clone();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx.send(());
            });
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx2.send(());
            });
            rx.recv();
            rx.recv();
            Timer::new().unwrap().sleep(Duration::seconds(1));
            match server.poll() {
                Some((Command(PacketConnect), _))=> (),
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            };
            match server.poll() {
                Some((Command(PacketConnect), _))=> (),
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            }
            Timer::new().unwrap().sleep(Duration::seconds(1));
            assert!(server.all_connections().len() == 2);
            assert!(server.cull().len() == 2);
            assert!(server.all_connections().len() == 0);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can send to one
 */
#[test]
fn send_to_one() {
    let socket = 64006;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.set_timeout(Some(1000));
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Accept message
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Message message

                tx.send(Packet::deserialize(message[]).ok().expect("Couldn't deserialize a message"));
            });
            Timer::new().unwrap().sleep(Duration::seconds(1));
            let source = match server.poll() {
                Some((Command(PacketConnect), source)) => source,
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            };
            let message_out = vec![1,2];
            assert!(server.send_to(&message_out, &source) == true);
            let message = rx.recv();
            assert!(message.packet_type == PacketMessage);
            assert!(message.packet_content.unwrap() == message_out);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can't send to folks who aren't connected
 */
#[test]
fn send_to_disconnected() {
    let socket = 64007;
    let (my_addr, settings) = generate_settings(socket, 121);

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            assert!(server.send_to(&vec![1], &my_addr) == false);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can send to multiple folks
 */
#[test]
fn send_to_many() {
    let socket = 64008;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();
    let tx2 = tx.clone();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.set_timeout(Some(1000));
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Accept message
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Message message

                tx.send(Packet::deserialize(message[]).ok().expect("Couldn't deserialize a message"));
            });
            with_bound_socket!((socket) {
                socket.set_timeout(Some(1000));
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Accept message
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Message message

                tx2.send(Packet::deserialize(message[]).ok().expect("Couldn't deserialize a message"));
            });
            Timer::new().unwrap().sleep(Duration::seconds(1));
            let source = match server.poll() {
                Some((Command(PacketConnect), source)) => source,
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            };
            let source2 = match server.poll() {
                Some((Command(PacketConnect), source)) => source,
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            };
            let message_out = vec![1,2];
            server.send_to_many(&message_out, &vec![source, source2]);
            let message1 = rx.recv();
            let message2 = rx.recv();
            assert!(message1.packet_content.unwrap() == message2.packet_content.unwrap());
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can send to everyone connected
 */
#[test]
fn send_to_all() {
    unimplemented!()
}

/**
 * Test we can recieve messages
 */
#[test]
fn receive() {
    unimplemented!()
}

/**
 * Test we can handle client disconnects
 */
#[test]
fn client_disconnect() {
    unimplemented!()
}
<commit_msg>Send to all test<commit_after>#![feature(macro_rules)]
extern crate string_telephone;

use string_telephone::{ConnectionConfig, ClientConnectionConfig, Server, Packet, PollEmpty, PacketConnect, PacketMessage, PacketDisconnect, PollDisconnected, Command};
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::time::duration::Duration;
use std::io::net::udp::UdpSocket;
use std::io::Timer;

mod test_shared;

macro_rules! with_bound_socket(
    (($variable:ident)$code:block) => (
        spawn(proc() {
            match UdpSocket::bind(SocketAddr{ ip: Ipv4Addr(0, 0, 0, 0), port: 0 }) {
                Ok(mut $variable) => $code,
                Err(e) => fail!(e)
            }
        });
    )
)

fn generate_settings(port: u16, protocol_id: u32) -> (SocketAddr, ConnectionConfig<Vec<u8>>) {
    let my_addr = SocketAddr{ ip: Ipv4Addr(127, 0, 0, 1), port: port };
    let settings = ConnectionConfig::new(protocol_id, Duration::seconds(10), test_shared::deserializer, test_shared::serializer);
    (my_addr, settings)
}

/**
 * Test we can start listening
 */
#[test]
fn create_server() {
    let socket = 64000;
    let (my_addr, settings) = generate_settings(socket, 121);
    match Server::new(my_addr, settings) {
        Ok(_) => (), //passed
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we get empty polls when we have no clients
 */
#[test]
fn empty_poll() {
    let socket = 64001;
    let (my_addr, settings) = generate_settings(socket, 121);
    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            assert!(server.poll().is_none())
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we reject bad connection attempts
 */
#[test]
fn bad_client_attempt() {
    let socket = 64002;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(122).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx.send(());
            });
            rx.recv();
            Timer::new().unwrap().sleep(Duration::seconds(1));
            assert!(server.poll().is_none())
            assert!(server.all_connections().len() == 0);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can take a single client
 */
#[test]
fn single_client() {
    let socket = 64003;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx.send(());
            });
            rx.recv();
            Timer::new().unwrap().sleep(Duration::seconds(1));
            match server.poll() {
                Some((Command(PacketConnect), _))=> (),
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            }
            assert!(server.all_connections().len() == 1);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can take multiple clients
 */
#[test]
fn multiple_clients() {
    let socket = 64004;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();
    let tx2 = tx.clone();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx.send(());
            });
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx2.send(());
            });
            rx.recv();
            rx.recv();
            Timer::new().unwrap().sleep(Duration::seconds(1));
            match server.poll() {
                Some((Command(PacketConnect), _))=> (),
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            };
            match server.poll() {
                Some((Command(PacketConnect), _))=> (),
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            }
            assert!(server.all_connections().len() == 2);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can cull old clients
 */
#[test]
fn cull() {
    let socket = 64005;
    let (my_addr, mut settings) = generate_settings(socket, 121);
    settings.timeout_period = Duration::seconds(0);
    let (tx, rx) = channel();
    let tx2 = tx.clone();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx.send(());
            });
            with_bound_socket!((socket) {
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                tx2.send(());
            });
            rx.recv();
            rx.recv();
            Timer::new().unwrap().sleep(Duration::seconds(1));
            match server.poll() {
                Some((Command(PacketConnect), _))=> (),
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            };
            match server.poll() {
                Some((Command(PacketConnect), _))=> (),
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            }
            Timer::new().unwrap().sleep(Duration::seconds(1));
            assert!(server.all_connections().len() == 2);
            assert!(server.cull().len() == 2);
            assert!(server.all_connections().len() == 0);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can send to one
 */
#[test]
fn send_to_one() {
    let socket = 64006;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.set_timeout(Some(1000));
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Accept message
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Message message

                tx.send(Packet::deserialize(message[]).ok().expect("Couldn't deserialize a message"));
            });
            Timer::new().unwrap().sleep(Duration::seconds(1));
            let source = match server.poll() {
                Some((Command(PacketConnect), source)) => source,
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            };
            let message_out = vec![1,2];
            assert!(server.send_to(&message_out, &source) == true);
            let message = rx.recv();
            assert!(message.packet_type == PacketMessage);
            assert!(message.packet_content.unwrap() == message_out);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can't send to folks who aren't connected
 */
#[test]
fn send_to_disconnected() {
    let socket = 64007;
    let (my_addr, settings) = generate_settings(socket, 121);

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            assert!(server.send_to(&vec![1], &my_addr) == false);
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can send to multiple folks
 */
#[test]
fn send_to_many() {
    let socket = 64008;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();
    let tx2 = tx.clone();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.set_timeout(Some(1000));
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Accept message
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Message message

                tx.send(Packet::deserialize(message[]).ok().expect("Couldn't deserialize a message"));
            });
            with_bound_socket!((socket) {
                socket.set_timeout(Some(1000));
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Accept message
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Message message

                tx2.send(Packet::deserialize(message[]).ok().expect("Couldn't deserialize a message"));
            });
            Timer::new().unwrap().sleep(Duration::seconds(1));
            let source = match server.poll() {
                Some((Command(PacketConnect), source)) => source,
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            };
            let source2 = match server.poll() {
                Some((Command(PacketConnect), source)) => source,
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            };
            let message_out = vec![1,2];
            server.send_to_many(&message_out, &vec![source, source2]);
            let message1 = rx.recv();
            let message2 = rx.recv();
            assert!(message1.packet_content.unwrap() == message2.packet_content.unwrap());
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can send to everyone connected
 */
#[test]
fn send_to_all() {
    let socket = 64009;
    let (my_addr, settings) = generate_settings(socket, 121);
    let (tx, rx) = channel();
    let tx2 = tx.clone();

    match Server::new(my_addr, settings) {
        Ok(ref mut server) => {
            with_bound_socket!((socket) {
                socket.set_timeout(Some(1000));
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Accept message
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Message message

                tx.send(Packet::deserialize(message[]).ok().expect("Couldn't deserialize a message"));
            });
            with_bound_socket!((socket) {
                socket.set_timeout(Some(1000));
                socket.send_to(Packet::connect(121).serialize().unwrap()[], my_addr).ok().expect("Couldn't send a message");
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Accept message
                let (message, _) = test_shared::get_message(&mut socket); //Should be the Message message

                tx2.send(Packet::deserialize(message[]).ok().expect("Couldn't deserialize a message"));
            });
            Timer::new().unwrap().sleep(Duration::seconds(1));
            let source = match server.poll() {
                Some((Command(PacketConnect), source)) => source,
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            };
            let source2 = match server.poll() {
                Some((Command(PacketConnect), source)) => source,
                None => fail!("No result found"),
                _ => fail!("Unexpected poll result")
            };
            let message_out = vec![1,2];
            server.send_to_all(&message_out);
            let message1 = rx.recv();
            let message2 = rx.recv();
            assert!(message1.packet_content.unwrap() == message2.packet_content.unwrap());
        },
        Err(t) => fail!("Failed to create a server - {}", t)
    };
}

/**
 * Test we can recieve messages
 */
#[test]
fn receive() {
    unimplemented!()
}

/**
 * Test we can handle client disconnects
 */
#[test]
fn client_disconnect() {
    unimplemented!()
}
<|endoftext|>