<commit_before>extern crate rand;
extern crate regex;

use self::rand::{thread_rng, Rng};
use self::regex::Regex;
use crate::common::util::*;
use rand::SeedableRng;
#[cfg(not(windows))]
use std::env;
use std::io::Write;
use std::path::Path;
use std::{
    fs::{read_dir, File},
    io::BufWriter,
};

fn random_chars(n: usize) -> String {
    thread_rng()
        .sample_iter(&rand::distributions::Alphanumeric)
        .take(n)
        .collect::<String>()
}

struct Glob {
    directory: AtPath,
    regex: Regex,
}

impl Glob {
    fn new(at: &AtPath, directory: &str, regex: &str) -> Glob {
        Glob {
            directory: AtPath::new(Path::new(&at.plus_as_string(directory))),
            regex: Regex::new(regex).unwrap(),
        }
    }

    fn count(&self) -> usize {
        self.collect().len()
    }

    /// Get all files in `self.directory` that match `self.regex`
    fn collect(&self) -> Vec<String> {
        read_dir(Path::new(&self.directory.subdir))
            .unwrap()
            .filter_map(|entry| {
                let path = entry.unwrap().path();
                let name = self
                    .directory
                    .minus_as_string(path.as_path().to_str().unwrap_or(""));
                if self.regex.is_match(&name) {
                    Some(name)
                } else {
                    None
                }
            })
            .collect()
    }

    /// Accumulate bytes of all files in `self.collect()`
    fn collate(&self) -> Vec<u8> {
        let mut files = self.collect();
        files.sort();
        let mut data: Vec<u8> = vec![];
        for name in &files {
            data.extend(self.directory.read_bytes(name));
        }
        data
    }
}

/// File handle that user can add random bytes (line-formatted or not) to
struct RandomFile {
    inner: File,
}

impl RandomFile {
    /// Size of each line that's being generated
    const LINESIZE: usize = 32;

    /// `create()` file handle located at `at` / `name`
    fn new(at: &AtPath, name: &str) -> RandomFile {
        RandomFile {
            inner: File::create(&at.plus(name)).unwrap(),
        }
    }

    fn add_bytes(&mut self, bytes: usize) {
        // Note that just writing random characters isn't enough to cover all
        // cases. We need truly random bytes.
        let mut writer = BufWriter::new(&self.inner);

        // Seed the rng so as to avoid spurious test failures.
        let mut rng = rand::rngs::StdRng::seed_from_u64(123);
        let mut buffer = [0; 1024];
        let mut remaining_size = bytes;

        while remaining_size > 0 {
            let to_write = std::cmp::min(remaining_size, buffer.len());
            let buf = &mut buffer[..to_write];
            rng.fill(buf);
            writer.write(buf).unwrap();

            remaining_size -= to_write;
        }
    }

    /// Add n lines each of size `RandomFile::LINESIZE`
    fn add_lines(&mut self, lines: usize) {
        let mut n = lines;
        while n > 0 {
            writeln!(self.inner, "{}", random_chars(RandomFile::LINESIZE)).unwrap();
            n -= 1;
        }
    }
}

#[test]
fn test_split_default() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "split_default";
    RandomFile::new(&at, name).add_lines(2000);
    ucmd.args(&[name]).succeeds();

    let glob = Glob::new(&at, ".", r"x[[:alpha:]][[:alpha:]]$");
    assert_eq!(glob.count(), 2);
    assert_eq!(glob.collate(), at.read_bytes(name));
}

#[test]
fn test_split_numeric_prefixed_chunks_by_bytes() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "split_num_prefixed_chunks_by_bytes";
    RandomFile::new(&at, name).add_bytes(10000);
    ucmd.args(&[
        "-d", // --numeric-suffixes
        "-b", // --bytes
        "1000", name, "a",
    ])
    .succeeds();

    let glob = Glob::new(&at, ".", r"a\d\d$");
    assert_eq!(glob.count(), 10);
    for filename in glob.collect() {
        assert_eq!(glob.directory.metadata(&filename).len(), 1000);
    }
    assert_eq!(glob.collate(), at.read_bytes(name));
}

#[test]
fn test_split_str_prefixed_chunks_by_bytes() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "split_str_prefixed_chunks_by_bytes";
    RandomFile::new(&at, name).add_bytes(10000);
    // Important that this is less than 1024 since that's our internal buffer
    // size. Good to test that we don't overshoot.
    ucmd.args(&["-b", "1000", name, "b"]).succeeds();

    let glob = Glob::new(&at, ".", r"b[[:alpha:]][[:alpha:]]$");
    assert_eq!(glob.count(), 10);
    for filename in glob.collect() {
        assert_eq!(glob.directory.metadata(&filename).len(), 1000);
    }
    assert_eq!(glob.collate(), at.read_bytes(name));
}

// This is designed to test what happens when the desired part size is not a
// multiple of the buffer size and we hopefully don't overshoot the desired part
// size.
#[test]
fn test_split_bytes_prime_part_size() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "test_split_bytes_prime_part_size";
    RandomFile::new(&at, name).add_bytes(10000);
    // 1753 is prime and greater than the buffer size, 1024.
    ucmd.args(&["-b", "1753", name, "b"]).succeeds();

    let glob = Glob::new(&at, ".", r"b[[:alpha:]][[:alpha:]]$");
    assert_eq!(glob.count(), 6);
    for i in 0..5 {
        assert_eq!(glob.directory.metadata(&glob.collect()[i]).len(), 1753);
    }
    assert_eq!(glob.directory.metadata(&glob.collect()[5]).len(), 1235);
    assert_eq!(glob.collate(), at.read_bytes(name));
}

#[test]
fn test_split_num_prefixed_chunks_by_lines() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "split_num_prefixed_chunks_by_lines";
    RandomFile::new(&at, name).add_lines(10000);
    ucmd.args(&["-d", "-l", "1000", name, "c"]).succeeds();

    let glob = Glob::new(&at, ".", r"c\d\d$");
    assert_eq!(glob.count(), 10);
    assert_eq!(glob.collate(), at.read_bytes(name));
}

#[test]
fn test_split_str_prefixed_chunks_by_lines() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "split_str_prefixed_chunks_by_lines";
    RandomFile::new(&at, name).add_lines(10000);
    ucmd.args(&["-l", "1000", name, "d"]).succeeds();

    let glob = Glob::new(&at, ".", r"d[[:alpha:]][[:alpha:]]$");
    assert_eq!(glob.count(), 10);
    assert_eq!(glob.collate(), at.read_bytes(name));
}

#[test]
fn test_split_additional_suffix() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "split_additional_suffix";
    RandomFile::new(&at, name).add_lines(2000);
    ucmd.args(&["--additional-suffix", ".txt", name]).succeeds();

    let glob = Glob::new(&at, ".", r"x[[:alpha:]][[:alpha:]].txt$");
    assert_eq!(glob.count(), 2);
    assert_eq!(glob.collate(), at.read_bytes(name));
}

// note: the test_filter* tests below are unix-only
// windows support has been waived for now because of the difficulty of getting
// the `cmd` call right
// see https://github.com/rust-lang/rust/issues/29494

#[test]
#[cfg(unix)]
fn test_filter() {
    // like `test_split_default()` but run a command before writing
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "filtered";
    let n_lines = 3;
    RandomFile::new(&at, name).add_lines(n_lines);

    // change all characters to 'i'
    ucmd.args(&["--filter=sed s/./i/g > $FILE", name])
        .succeeds();

    // assert all characters are 'i' / no character is not 'i'
    // (assert that command succeded)
    let glob = Glob::new(&at, ".", r"x[[:alpha:]][[:alpha:]]$");
    assert!(
        glob.collate().iter().find(|&&c| {
            // is not i
            c != ('i' as u8)
            // is not newline
            && c != ('\n' as u8)
        }) == None
    );
}

#[test]
#[cfg(unix)]
fn test_filter_with_env_var_set() {
    // This test will ensure that if $FILE env var was set before running --filter, it'll stay that
    // way
    // implemented like `test_split_default()` but run a command before writing
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "filtered";
    let n_lines = 3;
    RandomFile::new(&at, name).add_lines(n_lines);

    let env_var_value = "somevalue";
    env::set_var("FILE", &env_var_value);
    ucmd.args(&[format!("--filter={}", "cat > $FILE").as_str(), name])
        .succeeds();

    let glob = Glob::new(&at, ".", r"x[[:alpha:]][[:alpha:]]$");
    assert_eq!(glob.collate(), at.read_bytes(name));
    assert!(env::var("FILE").unwrap_or("var was unset".to_owned()) == env_var_value);
}

#[test]
#[cfg(unix)]
fn test_filter_command_fails() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "filter-will-fail";
    RandomFile::new(&at, name).add_lines(4);

    ucmd.args(&["--filter=/a/path/that/totally/does/not/exist", name])
        .fails();
}
<commit_msg>Fix test_split_bytes_prime_part_size<commit_after>extern crate rand;
extern crate regex;

use self::rand::{thread_rng, Rng};
use self::regex::Regex;
use crate::common::util::*;
use rand::SeedableRng;
#[cfg(not(windows))]
use std::env;
use std::io::Write;
use std::path::Path;
use std::{
    fs::{read_dir, File},
    io::BufWriter,
};

fn random_chars(n: usize) -> String {
    thread_rng()
        .sample_iter(&rand::distributions::Alphanumeric)
        .take(n)
        .collect::<String>()
}

struct Glob {
    directory: AtPath,
    regex: Regex,
}

impl Glob {
    fn new(at: &AtPath, directory: &str, regex: &str) -> Glob {
        Glob {
            directory: AtPath::new(Path::new(&at.plus_as_string(directory))),
            regex: Regex::new(regex).unwrap(),
        }
    }

    fn count(&self) -> usize {
        self.collect().len()
    }

    /// Get all files in `self.directory` that match `self.regex`
    fn collect(&self) -> Vec<String> {
        read_dir(Path::new(&self.directory.subdir))
            .unwrap()
            .filter_map(|entry| {
                let path = entry.unwrap().path();
                let name = self
                    .directory
                    .minus_as_string(path.as_path().to_str().unwrap_or(""));
                if self.regex.is_match(&name) {
                    Some(name)
                } else {
                    None
                }
            })
            .collect()
    }

    /// Accumulate bytes of all files in `self.collect()`
    fn collate(&self) -> Vec<u8> {
        let mut files = self.collect();
        files.sort();
        let mut data: Vec<u8> = vec![];
        for name in &files {
            data.extend(self.directory.read_bytes(name));
        }
        data
    }
}

/// File handle that user can add random bytes (line-formatted or not) to
struct RandomFile {
    inner: File,
}

impl RandomFile {
    /// Size of each line that's being generated
    const LINESIZE: usize = 32;

    /// `create()` file handle located at `at` / `name`
    fn new(at: &AtPath, name: &str) -> RandomFile {
        RandomFile {
            inner: File::create(&at.plus(name)).unwrap(),
        }
    }

    fn add_bytes(&mut self, bytes: usize) {
        // Note that just writing random characters isn't enough to cover all
        // cases. We need truly random bytes.
        let mut writer = BufWriter::new(&self.inner);

        // Seed the rng so as to avoid spurious test failures.
        let mut rng = rand::rngs::StdRng::seed_from_u64(123);
        let mut buffer = [0; 1024];
        let mut remaining_size = bytes;

        while remaining_size > 0 {
            let to_write = std::cmp::min(remaining_size, buffer.len());
            let buf = &mut buffer[..to_write];
            rng.fill(buf);
            writer.write(buf).unwrap();

            remaining_size -= to_write;
        }
    }

    /// Add n lines each of size `RandomFile::LINESIZE`
    fn add_lines(&mut self, lines: usize) {
        let mut n = lines;
        while n > 0 {
            writeln!(self.inner, "{}", random_chars(RandomFile::LINESIZE)).unwrap();
            n -= 1;
        }
    }
}

#[test]
fn test_split_default() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "split_default";
    RandomFile::new(&at, name).add_lines(2000);
    ucmd.args(&[name]).succeeds();

    let glob = Glob::new(&at, ".", r"x[[:alpha:]][[:alpha:]]$");
    assert_eq!(glob.count(), 2);
    assert_eq!(glob.collate(), at.read_bytes(name));
}

#[test]
fn test_split_numeric_prefixed_chunks_by_bytes() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "split_num_prefixed_chunks_by_bytes";
    RandomFile::new(&at, name).add_bytes(10000);
    ucmd.args(&[
        "-d", // --numeric-suffixes
        "-b", // --bytes
        "1000", name, "a",
    ])
    .succeeds();

    let glob = Glob::new(&at, ".", r"a\d\d$");
    assert_eq!(glob.count(), 10);
    for filename in glob.collect() {
        assert_eq!(glob.directory.metadata(&filename).len(), 1000);
    }
    assert_eq!(glob.collate(), at.read_bytes(name));
}

#[test]
fn test_split_str_prefixed_chunks_by_bytes() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "split_str_prefixed_chunks_by_bytes";
    RandomFile::new(&at, name).add_bytes(10000);
    // Important that this is less than 1024 since that's our internal buffer
    // size. Good to test that we don't overshoot.
    ucmd.args(&["-b", "1000", name, "b"]).succeeds();

    let glob = Glob::new(&at, ".", r"b[[:alpha:]][[:alpha:]]$");
    assert_eq!(glob.count(), 10);
    for filename in glob.collect() {
        assert_eq!(glob.directory.metadata(&filename).len(), 1000);
    }
    assert_eq!(glob.collate(), at.read_bytes(name));
}

// This is designed to test what happens when the desired part size is not a
// multiple of the buffer size and we hopefully don't overshoot the desired part
// size.
#[test]
fn test_split_bytes_prime_part_size() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "test_split_bytes_prime_part_size";
    RandomFile::new(&at, name).add_bytes(10000);
    // 1753 is prime and greater than the buffer size, 1024.
    ucmd.args(&["-b", "1753", name, "b"]).succeeds();

    let glob = Glob::new(&at, ".", r"b[[:alpha:]][[:alpha:]]$");
    assert_eq!(glob.count(), 6);
    let mut fns = glob.collect();
    // glob.collect() is not guaranteed to return in sorted order, so we sort.
    fns.sort();
    for i in 0..5 {
        assert_eq!(glob.directory.metadata(&fns[i]).len(), 1753);
    }
    assert_eq!(glob.directory.metadata(&fns[5]).len(), 1235);
    assert_eq!(glob.collate(), at.read_bytes(name));
}

#[test]
fn test_split_num_prefixed_chunks_by_lines() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "split_num_prefixed_chunks_by_lines";
    RandomFile::new(&at, name).add_lines(10000);
    ucmd.args(&["-d", "-l", "1000", name, "c"]).succeeds();

    let glob = Glob::new(&at, ".", r"c\d\d$");
    assert_eq!(glob.count(), 10);
    assert_eq!(glob.collate(), at.read_bytes(name));
}

#[test]
fn test_split_str_prefixed_chunks_by_lines() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "split_str_prefixed_chunks_by_lines";
    RandomFile::new(&at, name).add_lines(10000);
    ucmd.args(&["-l", "1000", name, "d"]).succeeds();

    let glob = Glob::new(&at, ".", r"d[[:alpha:]][[:alpha:]]$");
    assert_eq!(glob.count(), 10);
    assert_eq!(glob.collate(), at.read_bytes(name));
}

#[test]
fn test_split_additional_suffix() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "split_additional_suffix";
    RandomFile::new(&at, name).add_lines(2000);
    ucmd.args(&["--additional-suffix", ".txt", name]).succeeds();

    let glob = Glob::new(&at, ".", r"x[[:alpha:]][[:alpha:]].txt$");
    assert_eq!(glob.count(), 2);
    assert_eq!(glob.collate(), at.read_bytes(name));
}

// note: the test_filter* tests below are unix-only
// windows support has been waived for now because of the difficulty of getting
// the `cmd` call right
// see https://github.com/rust-lang/rust/issues/29494

#[test]
#[cfg(unix)]
fn test_filter() {
    // like `test_split_default()` but run a command before writing
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "filtered";
    let n_lines = 3;
    RandomFile::new(&at, name).add_lines(n_lines);

    // change all characters to 'i'
    ucmd.args(&["--filter=sed s/./i/g > $FILE", name])
        .succeeds();

    // assert all characters are 'i' / no character is not 'i'
    // (assert that command succeded)
    let glob = Glob::new(&at, ".", r"x[[:alpha:]][[:alpha:]]$");
    assert!(
        glob.collate().iter().find(|&&c| {
            // is not i
            c != ('i' as u8)
            // is not newline
            && c != ('\n' as u8)
        }) == None
    );
}

#[test]
#[cfg(unix)]
fn test_filter_with_env_var_set() {
    // This test will ensure that if $FILE env var was set before running --filter, it'll stay that
    // way
    // implemented like `test_split_default()` but run a command before writing
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "filtered";
    let n_lines = 3;
    RandomFile::new(&at, name).add_lines(n_lines);

    let env_var_value = "somevalue";
    env::set_var("FILE", &env_var_value);
    ucmd.args(&[format!("--filter={}", "cat > $FILE").as_str(), name])
        .succeeds();

    let glob = Glob::new(&at, ".", r"x[[:alpha:]][[:alpha:]]$");
    assert_eq!(glob.collate(), at.read_bytes(name));
    assert!(env::var("FILE").unwrap_or("var was unset".to_owned()) == env_var_value);
}

#[test]
#[cfg(unix)]
fn test_filter_command_fails() {
    let (at, mut ucmd) = at_and_ucmd!();
    let name = "filter-will-fail";
    RandomFile::new(&at, name).add_lines(4);

    ucmd.args(&["--filter=/a/path/that/totally/does/not/exist", name])
        .fails();
}
<|endoftext|>


<commit_before>use crate::common::util::*;

#[test]
fn test_uname_compatible() {
    new_ucmd!().arg("-a").succeeds();
}

#[test]
fn test_uname_name() {
    new_ucmd!().arg("-n").succeeds();
}

#[test]
fn test_uname_processor() {
    let result = new_ucmd!().arg("-p").succeeds();
    assert_eq!(result.stdout_str().trim_end(), "unknown");
}

#[test]
fn test_uname_hwplatform() {
    let result = new_ucmd!().arg("-i").succeeds();
    assert_eq!(result.stdout_str().trim_end(), "unknown");
}

#[test]
fn test_uname_machine() {
    new_ucmd!().arg("-m").succeeds();
}

#[test]
fn test_uname_kernel_version() {
    new_ucmd!().arg("-v").succeeds();
}

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

    let result = ucmd.arg("-o").succeeds();
    #[cfg(target_os = "linux")]
    assert!(result.stdout_str().to_lowercase().contains("linux"));
}
<commit_msg>uname(test): fix 'unused variable: result'<commit_after>use crate::common::util::*;

#[test]
fn test_uname_compatible() {
    new_ucmd!().arg("-a").succeeds();
}

#[test]
fn test_uname_name() {
    new_ucmd!().arg("-n").succeeds();
}

#[test]
fn test_uname_processor() {
    let result = new_ucmd!().arg("-p").succeeds();
    assert_eq!(result.stdout_str().trim_end(), "unknown");
}

#[test]
fn test_uname_hwplatform() {
    let result = new_ucmd!().arg("-i").succeeds();
    assert_eq!(result.stdout_str().trim_end(), "unknown");
}

#[test]
fn test_uname_machine() {
    new_ucmd!().arg("-m").succeeds();
}

#[test]
fn test_uname_kernel_version() {
    new_ucmd!().arg("-v").succeeds();
}

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

    #[cfg(target_os = "linux")]
    {
        let result = ucmd.arg("-o").succeeds();
        assert!(result.stdout_str().to_lowercase().contains("linux"));
    }

    #[cfg(not(target_os = "linux"))]
    let result = ucmd.arg("-o").succeeds();
}
<|endoftext|>


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

#[macro_use]
extern crate nom;

use nom::IResult;
use std::env;
use std::fs::File;

#[derive(Debug)]
struct Request<'a> {
    method:  &'a [u8],
    uri:     &'a [u8],
    version: &'a [u8],
}

#[derive(Debug)]
struct Header<'a> {
    name:  &'a [u8],
    value: Vec<&'a [u8]>,
}

fn is_token(c: u8) -> bool {
    match c {
        128...255 => false,
        0...31    => false,
        b'('      => false,
        b')'      => false,
        b'<'      => false,
        b'>'      => false,
        b'@'      => false,
        b','      => false,
        b';'      => false,
        b':'      => false,
        b'\\'     => false,
        b'"'      => false,
        b'/'      => false,
        b'['      => false,
        b']'      => false,
        b'?'      => false,
        b'='      => false,
        b'{'      => false,
        b'}'      => false,
        b' '      => false,
        _         => true,
    }
}

fn not_line_ending(c: u8) -> bool {
    c != b'\r' && c != b'\n'
}

fn is_space(c: u8) -> bool {
    c == b' '
}

fn is_not_space(c: u8)        -> bool { c != b' ' }
fn is_horizontal_space(c: u8) -> bool { c == b' ' || c == b'\t' }

fn is_version(c: u8) -> bool {
    c >= b'0' && c <= b'9' || c == b'.'
}

named!(line_ending, alt!(tag!("\r\n") | tag!("\n")));

fn request_line<'a>(input: &'a [u8]) -> IResult<&'a[u8], Request<'a>> {
  chain!(input,
    method: take_while1!(is_token)     ~
            take_while1!(is_space)     ~
    url:    take_while1!(is_not_space) ~
            take_while1!(is_space)     ~
    version: http_version              ~
    line_ending,

    || Request {
        method: method,
        uri:    url,
        version: version,
    })
}

named!(http_version, chain!(
    tag!("HTTP/")                    ~
    version: take_while1!(is_version),

    || version));

named!(message_header_value, chain!(
          take_while1!(is_horizontal_space) ~
    data: take_while1!(not_line_ending)     ~
    line_ending,

    || data));

fn message_header<'a>(input: &'a [u8]) -> IResult<&'a[u8], Header<'a>> {
  chain!(input,
    name:   take_while1!(is_token) ~
            char!(':') ~
    values: many1!(message_header_value),

    || Header {
        name: name,
        value: values,
    })
}

fn request<'a>(input: &'a [u8]) -> IResult<&'a[u8], (Request<'a>, Vec<Header<'a>>)> {
  chain!(input,
    req: request_line           ~
    h:   many1!(message_header) ~
         line_ending,

    || (req, h))
}

fn parse(data:&[u8]) -> Option<Vec<(Request, Vec<Header>)>> {
  let mut buf = &data[..];
  let mut v = Vec::new();
  loop {
    match request(buf) {
      IResult::Done(b, r) => {
        buf = b;
        v.push(r);

        if b.is_empty() {

    //println!("{}", i);
          break;
        }
      },
      IResult::Error(_) => return None/*panic!("{:?}", e)*/,
      IResult::Incomplete(_) => return None/*panic!("Incomplete!")*/,
    }
  }

  Some(v)
}

use test::Bencher;

/*
#[bench]
fn small_test(b: &mut Bencher) {
  let data = include_bytes!("../../http-requests.txt");
  b.iter(||{
    parse(data)
  });
}

#[bench]
fn bigger_test(b: &mut Bencher) {
  let data = include_bytes!("../../bigger.txt");
  b.iter(||{
    parse(data)
  });
}
*/

#[bench]
fn one_test(b: &mut Bencher) {
  let data = &b"GET / HTTP/1.1
Host: www.reddit.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive"[..];
  b.iter(||{
    parse(data)
  });
}

fn main() {
    let mut contents: Vec<u8> = Vec::new();

    {
        use std::io::Read;

        let mut file = File::open(env::args().nth(1).expect("File to read")).ok().expect("Failed to open file");

        let _ = file.read_to_end(&mut contents).unwrap();
    }

    let buf = &contents[..];
    loop { parse(buf); }
}

<commit_msg>benches/http: switch to do_parse<commit_after>#![feature(test)]
extern crate test;

#[macro_use]
extern crate nom;

use nom::IResult;
use std::env;
use std::fs::File;

#[derive(Debug)]
struct Request<'a> {
    method:  &'a [u8],
    uri:     &'a [u8],
    version: &'a [u8],
}

#[derive(Debug)]
struct Header<'a> {
    name:  &'a [u8],
    value: Vec<&'a [u8]>,
}

fn is_token(c: u8) -> bool {
    match c {
        128...255 => false,
        0...31    => false,
        b'('      => false,
        b')'      => false,
        b'<'      => false,
        b'>'      => false,
        b'@'      => false,
        b','      => false,
        b';'      => false,
        b':'      => false,
        b'\\'     => false,
        b'"'      => false,
        b'/'      => false,
        b'['      => false,
        b']'      => false,
        b'?'      => false,
        b'='      => false,
        b'{'      => false,
        b'}'      => false,
        b' '      => false,
        _         => true,
    }
}

fn not_line_ending(c: u8) -> bool {
    c != b'\r' && c != b'\n'
}

fn is_space(c: u8) -> bool {
    c == b' '
}

fn is_not_space(c: u8)        -> bool { c != b' ' }
fn is_horizontal_space(c: u8) -> bool { c == b' ' || c == b'\t' }

fn is_version(c: u8) -> bool {
    c >= b'0' && c <= b'9' || c == b'.'
}

named!(line_ending, alt!(tag!("\r\n") | tag!("\n")));

fn request_line<'a>(input: &'a [u8]) -> IResult<&'a[u8], Request<'a>> {
  do_parse!(input,
    method: take_while1!(is_token)     >>
            take_while1!(is_space)     >>
    url:    take_while1!(is_not_space) >>
            take_while1!(is_space)     >>
    version: http_version              >>
    line_ending                        >>

    (Request {
        method: method,
        uri:    url,
        version: version,
    }))
}

named!(http_version, do_parse!(
    tag!("HTTP/")                     >>
    version: take_while1!(is_version) >>

    (version)));

named!(message_header_value, do_parse!(
          take_while1!(is_horizontal_space) >>
    data: take_while1!(not_line_ending)     >>
    line_ending                             >>

    (data)));

fn message_header<'a>(input: &'a [u8]) -> IResult<&'a[u8], Header<'a>> {
  do_parse!(input,
    name:   take_while1!(is_token)       >>
            char!(':')                   >>
    values: many1!(message_header_value) >>

    (Header {
        name: name,
        value: values,
    }))
}

fn request<'a>(input: &'a [u8]) -> IResult<&'a[u8], (Request<'a>, Vec<Header<'a>>)> {
  do_parse!(input,
    req: request_line           >>
    h:   many1!(message_header) >>
         line_ending            >>

    (req, h))
}

fn parse(data:&[u8]) -> Option<Vec<(Request, Vec<Header>)>> {
  let mut buf = &data[..];
  let mut v = Vec::new();
  loop {
    match request(buf) {
      IResult::Done(b, r) => {
        buf = b;
        v.push(r);

        if b.is_empty() {

    //println!("{}", i);
          break;
        }
      },
      IResult::Error(_) => return None/*panic!("{:?}", e)*/,
      IResult::Incomplete(_) => return None/*panic!("Incomplete!")*/,
    }
  }

  Some(v)
}

use test::Bencher;

/*
#[bench]
fn small_test(b: &mut Bencher) {
  let data = include_bytes!("../../http-requests.txt");
  b.iter(||{
    parse(data)
  });
}

#[bench]
fn bigger_test(b: &mut Bencher) {
  let data = include_bytes!("../../bigger.txt");
  b.iter(||{
    parse(data)
  });
}
*/

#[bench]
fn one_test(b: &mut Bencher) {
  let data = &b"GET / HTTP/1.1
Host: www.reddit.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:15.0) Gecko/20100101 Firefox/15.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive"[..];
  b.iter(||{
    parse(data)
  });
}

fn main() {
    let mut contents: Vec<u8> = Vec::new();

    {
        use std::io::Read;

        let mut file = File::open(env::args().nth(1).expect("File to read")).ok().expect("Failed to open file");

        let _ = file.read_to_end(&mut contents).unwrap();
    }

    let buf = &contents[..];
    loop { parse(buf); }
}

<|endoftext|>


<commit_before>#![feature(test)]
extern crate parser_combinators as pc;
extern crate test;

use std::collections::HashMap;
use std::io::Read;
use std::fs::File;
use std::path::Path;

use pc::primitives::{Parser, State, Stream};
use pc::combinator::{any, between, many, many1, optional, parser, satisfy, sep_by, unexpected, Expected, FnParser, Skip, ParserExt};
use pc::char::{char, digit, spaces, Spaces, string, ParseResult};

#[derive(PartialEq, Debug)]
enum Value {
    Number(f64),
    String(String),
    Bool(bool),
    Null,
    Object(HashMap<String, Value>),
    Array(Vec<Value>)
}

fn lex<'a, P>(p: P) -> Skip<P, Spaces<P::Input>>
    where P: Parser
        , P::Input: Stream<Item=char> {
    p.skip(spaces())
}
struct Json<I>(::std::marker::PhantomData<fn (I) -> I>);

type JsonParser<O, I> = Expected<FnParser<I, fn (State<I>) -> ParseResult<O, I>>>;

fn fn_parser<O, I>(f: fn(State<I>) -> ParseResult<O, I>, err: &'static str) -> JsonParser<O, I>
    where I: Stream<Item=char> {
    parser(f).expected(err)
}

impl <I> Json<I>
    where I: Stream<Item=char> {

    fn integer() -> JsonParser<i64, I> {
        fn_parser(Json::<I>::integer_, "integer")
    }
    fn integer_(input: State<I>) -> ParseResult<i64, I> {
        let (s, input) = try!(lex(many1::<String, _>(digit()))
            .parse_state(input));
        let mut n = 0;
        for c in s.chars() {
            n = n * 10 + (c as i64 - '0' as i64);
        }
        Ok((n, input))
    }

    fn number() -> JsonParser<f64, I> {
        fn_parser(Json::<I>::number_, "number")
    }
    fn number_(input: State<I>) -> ParseResult<f64, I> {
        let i = char('0').map(|_| 0.0)
                 .or(Json::<I>::integer().map(|x| x as f64));
        let fractional = many(digit())
            .map(|digits: String| {
                let mut magnitude = 1.0;
                digits.chars().fold(0.0, |acc, d| {
                    magnitude /= 10.0;
                    match d.to_digit(10) {
                        Some(d) => acc + (d as f64) * magnitude,
                        None => panic!("Not a digit")
                    }
                })
            });

        let exp = satisfy(|c| c == 'e' || c == 'E')
            .with(optional(char('-')).and(Json::<I>::integer()));
        lex(optional(char('-'))
            .and(i)
            .map(|(sign, n)| if sign.is_some() { -n } else { n })
            .and(optional(char('.')).with(fractional))
            .map(|(x, y)| if x > 0.0 { x + y } else { x - y })
            .and(optional(exp))
            .map(|(n, exp_option)| {
                match exp_option {
                    Some((sign, e)) => {
                        let e = if sign.is_some() { -e } else { e };
                        n * 10.0f64.powi(e as i32)
                    }
                    None => n
                }
            }))
        .parse_state(input)
    }

    fn char() -> JsonParser<char, I> {
        fn_parser(Json::<I>::char_, "char")
    }
    fn char_(input: State<I>) -> ParseResult<char, I> {
        let (c, input) = try!(any().parse_state(input));
        let mut back_slash_char = satisfy(|c| "\"\\/bfnrt".chars().find(|x| *x == c).is_some()).map(|c| {
            match c {
                '"' => '"',
                '\\' => '\\',
                '/' => '/',
                'b' => '\u{0008}',
                'f' => '\u{000c}',
                'n' => '\n',
                'r' => '\r',
                't' => '\t',
                c => c//Should never happen
            }
        });
        match c {
            '\\' => input.combine(|input| back_slash_char.parse_state(input)),
            '"'  => unexpected("\"").parse_state(input.into_inner()).map(|_| unreachable!()),
            _    => Ok((c, input))
        }
    }
    fn string() -> JsonParser<String, I> {
        fn_parser(Json::<I>::string_, "string")
    }
    fn string_(input: State<I>) -> ParseResult<String, I> {
        between(char('"'), lex(char('"')), many(Json::<I>::char()))
            .parse_state(input)
    }

    fn object() -> JsonParser<Value, I> {
        fn_parser(Json::<I>::object_, "object")
    }
    fn object_(input: State<I>) -> ParseResult<Value, I> {
        let field = (Json::<I>::string(), lex(char(':')), Json::<I>::value())
            .map(|t| (t.0, t.2));
        let fields = sep_by(field, lex(char(',')));
        between(lex(char('{')), lex(char('}')), fields)
            .map(Value::Object)
            .parse_state(input)
    }

    fn value() -> FnParser<I, fn (State<I>) -> ParseResult<Value, I>> {
        parser({ let f: fn (_) -> _ = Json::<I>::value_; f })
    }
    #[allow(unconditional_recursion)]
    fn value_(input: State<I>) -> ParseResult<Value, I> {
        let array = between(lex(char('[')), lex(char(']')), sep_by(Json::<I>::value(), lex(char(','))))
            .map(Value::Array);

        Json::<I>::string().map(Value::String)
            .or(Json::<I>::object())
            .or(array)
            .or(Json::<I>::number().map(Value::Number))
            .or(lex(string("false").map(|_| Value::Bool(false))
                .or(string("true").map(|_| Value::Bool(true)))
                .or(string("null").map(|_| Value::Null))))
            .parse_state(input)
    }
}

#[test]
fn json_test() {
    use self::Value::*;
    let input =
r#"
{
    "array": [1, ""],
    "object": {},
    "number": 3.14,
    "int": -100,
    "exp": -1e2,
    "exp_neg": 23e-2,
    "true": true,
    "false"  : false,
    "null" : null
}"#;
    let result = Json::value()
        .parse(input);
    let expected = Object(vec![
        ("array", Array(vec![Number(1.0), String("".to_string())])),
        ("object", Object(HashMap::new())),
        ("number", Number(3.14)),
        ("int", Number(-100.)),
        ("exp", Number(-1e2)),
        ("exp_neg", Number(23E-2)),
        ("true", Bool(true)),
        ("false", Bool(false)),
        ("null", Null)
    ].into_iter().map(|(k, v)| (k.to_string(), v)).collect());
    match result {
        Ok(result) => assert_eq!(result, (expected, "")),
        Err(e) => {
            println!("{}", e);
            assert!(false);
        }
    }
}

#[bench]
fn bench_json(bencher: &mut ::test::Bencher) {
    let mut data = String::new();
    File::open(&Path::new(&"benches/data.json"))
        .and_then(|mut file| file.read_to_string(&mut data))
        .unwrap();
    let mut parser = Json::value();
    match parser.parse(&data[..]) {
        Ok((Value::Array(_), "")) => (),
        Ok(x) => { println!("{:?}", x); assert!(false); }
        Err(err) => { println!("{}", err); assert!(false); }
    }
    bencher.iter(|| {
        let result = parser.parse(&data);
        ::test::black_box(result)
    });
}
<commit_msg>Minor speedup to the json parser ~5%<commit_after>#![feature(test)]
extern crate parser_combinators as pc;
extern crate test;

use std::collections::HashMap;
use std::io::Read;
use std::fs::File;
use std::path::Path;

use pc::primitives::{from_iter, Consumed, Parser, ParseError, State, Stream};
use pc::combinator::{any, between, many, many1, optional, parser, satisfy, sep_by, Expected, FnParser, Skip, ParserExt};
use pc::char::{char, digit, spaces, Spaces, string, ParseResult};

#[derive(PartialEq, Debug)]
enum Value {
    Number(f64),
    String(String),
    Bool(bool),
    Null,
    Object(HashMap<String, Value>),
    Array(Vec<Value>)
}

fn lex<'a, P>(p: P) -> Skip<P, Spaces<P::Input>>
    where P: Parser
        , P::Input: Stream<Item=char> {
    p.skip(spaces())
}
struct Json<I>(::std::marker::PhantomData<fn (I) -> I>);

type JsonParser<O, I> = Expected<FnParser<I, fn (State<I>) -> ParseResult<O, I>>>;

fn fn_parser<O, I>(f: fn(State<I>) -> ParseResult<O, I>, err: &'static str) -> JsonParser<O, I>
    where I: Stream<Item=char> {
    parser(f).expected(err)
}

impl <I> Json<I>
    where I: Stream<Item=char> {

    fn integer() -> JsonParser<i64, I> {
        fn_parser(Json::<I>::integer_, "integer")
    }
    fn integer_(input: State<I>) -> ParseResult<i64, I> {
        let (s, input) = try!(lex(many1::<String, _>(digit()))
            .parse_state(input));
        let mut n = 0;
        for c in s.chars() {
            n = n * 10 + (c as i64 - '0' as i64);
        }
        Ok((n, input))
    }

    fn number() -> JsonParser<f64, I> {
        fn_parser(Json::<I>::number_, "number")
    }
    fn number_(input: State<I>) -> ParseResult<f64, I> {
        let i = char('0').map(|_| 0.0)
                 .or(Json::<I>::integer().map(|x| x as f64));
        let fractional = many(digit())
            .map(|digits: String| {
                let mut magnitude = 1.0;
                digits.chars().fold(0.0, |acc, d| {
                    magnitude /= 10.0;
                    match d.to_digit(10) {
                        Some(d) => acc + (d as f64) * magnitude,
                        None => panic!("Not a digit")
                    }
                })
            });

        let exp = satisfy(|c| c == 'e' || c == 'E')
            .with(optional(char('-')).and(Json::<I>::integer()));
        lex(optional(char('-'))
            .and(i)
            .map(|(sign, n)| if sign.is_some() { -n } else { n })
            .and(optional(char('.')).with(fractional))
            .map(|(x, y)| if x > 0.0 { x + y } else { x - y })
            .and(optional(exp))
            .map(|(n, exp_option)| {
                match exp_option {
                    Some((sign, e)) => {
                        let e = if sign.is_some() { -e } else { e };
                        n * 10.0f64.powi(e as i32)
                    }
                    None => n
                }
            }))
        .parse_state(input)
    }

    fn char() -> JsonParser<char, I> {
        fn_parser(Json::<I>::char_, "char")
    }
    fn char_(input: State<I>) -> ParseResult<char, I> {
        let (c, input) = try!(any().parse_state(input));
        let mut back_slash_char = satisfy(|c| "\"\\/bfnrt".chars().find(|x| *x == c).is_some()).map(|c| {
            match c {
                '"' => '"',
                '\\' => '\\',
                '/' => '/',
                'b' => '\u{0008}',
                'f' => '\u{000c}',
                'n' => '\n',
                'r' => '\r',
                't' => '\t',
                c => c//Should never happen
            }
        });
        match c {
            '\\' => input.combine(|input| back_slash_char.parse_state(input)),
            '"'  => Err(Consumed::Empty(ParseError::from_errors(input.into_inner().position, Vec::new()))),
            _    => Ok((c, input))
        }
    }
    fn string() -> JsonParser<String, I> {
        fn_parser(Json::<I>::string_, "string")
    }
    fn string_(input: State<I>) -> ParseResult<String, I> {
        between(char('"'), lex(char('"')), many(Json::<I>::char()))
            .parse_state(input)
    }

    fn object() -> JsonParser<Value, I> {
        fn_parser(Json::<I>::object_, "object")
    }
    fn object_(input: State<I>) -> ParseResult<Value, I> {
        let field = (Json::<I>::string(), lex(char(':')), Json::<I>::value())
            .map(|t| (t.0, t.2));
        let fields = sep_by(field, lex(char(',')));
        between(lex(char('{')), lex(char('}')), fields)
            .map(Value::Object)
            .parse_state(input)
    }

    fn value() -> FnParser<I, fn (State<I>) -> ParseResult<Value, I>> {
        parser({ let f: fn (_) -> _ = Json::<I>::value_; f })
    }
    #[allow(unconditional_recursion)]
    fn value_(input: State<I>) -> ParseResult<Value, I> {
        let array = between(lex(char('[')), lex(char(']')), sep_by(Json::<I>::value(), lex(char(','))))
            .map(Value::Array);

        Json::<I>::string().map(Value::String)
            .or(Json::<I>::object())
            .or(array)
            .or(Json::<I>::number().map(Value::Number))
            .or(lex(string("false").map(|_| Value::Bool(false))
                .or(string("true").map(|_| Value::Bool(true)))
                .or(string("null").map(|_| Value::Null))))
            .parse_state(input)
    }
}

#[test]
fn json_test() {
    use self::Value::*;
    let input =
r#"
{
    "array": [1, ""],
    "object": {},
    "number": 3.14,
    "int": -100,
    "exp": -1e2,
    "exp_neg": 23e-2,
    "true": true,
    "false"  : false,
    "null" : null
}"#;
    let result = Json::value()
        .parse(input);
    let expected = Object(vec![
        ("array", Array(vec![Number(1.0), String("".to_string())])),
        ("object", Object(HashMap::new())),
        ("number", Number(3.14)),
        ("int", Number(-100.)),
        ("exp", Number(-1e2)),
        ("exp_neg", Number(23E-2)),
        ("true", Bool(true)),
        ("false", Bool(false)),
        ("null", Null)
    ].into_iter().map(|(k, v)| (k.to_string(), v)).collect());
    match result {
        Ok(result) => assert_eq!(result, (expected, "")),
        Err(e) => {
            println!("{}", e);
            assert!(false);
        }
    }
}

#[bench]
fn bench_json(bencher: &mut ::test::Bencher) {
    let mut data = String::new();
    File::open(&Path::new(&"benches/data.json"))
        .and_then(|mut file| file.read_to_string(&mut data))
        .unwrap();
    let mut parser = Json::value();
    let stream = from_iter(data.chars());
    match parser.parse(stream.clone()) {
        Ok((Value::Array(_), _)) => (),
        Ok(_) => assert!(false),
        Err(err) => { println!("{}", err); assert!(false); }
    }
    bencher.iter(|| {
        let result = parser.parse(stream.clone());
        ::test::black_box(result)
    });
}
<|endoftext|>


<commit_before>//
// Copyright 2017 yvt, all rights reserved.
//
// Licensed under the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>. This file may
// not be copied, modified,or distributed except
// according to those terms.
//
extern crate xalloc;

use xalloc::BitmapAlloc;
use std::ops;

struct Xorshift32(u32);

impl Xorshift32 {
    /// Returns a random integer in `[0, 0xfffffffe]`
    fn next(&mut self) -> u32 {
        self.0 ^= self.0 << 13;
        self.0 ^= self.0 >> 17;
        self.0 ^= self.0 << 5;
        !self.0
    }
    fn next_range(&mut self, range: ops::Range<u32>) -> u32 {
        let len = range.end - range.start;
        let mut mask = len - 1;
        mask |= mask >> 1;
        mask |= mask >> 2;
        mask |= mask >> 4;
        mask |= mask >> 8;
        mask |= mask >> 16;

        // Let's not care about the unbounded execution time :)
        let mut value = self.next() & mask;
        while value >= len {
            value = self.next() & mask;
        }

        value + range.start
    }
}

#[test]
fn create() {
    for i in 1..100 {
        println!("new({})", i);
        BitmapAlloc::new(i);
    }
}

#[test]
fn full_allocate() {
    for i in 1..100 {
        println!("new({})", i);
        let mut sa = BitmapAlloc::new(i);
        let result = sa.alloc(i);
        assert!(result.is_some());
    }
}

#[test]
fn allocate_two() {
    for i in 1..50 {
        for k in 1..i {
            println!("new({})", i);
            let mut sa = BitmapAlloc::new(i);
            println!("  alloc({})", k);
            let result1 = sa.alloc(k);
            assert!(result1.is_some());
            println!("  alloc({})", i - k);
            let result2 = sa.alloc((i - k));
            assert!(result2.is_some());
        }
    }
}

#[test]
fn allocate_three() {
    for i in 1..50 {
        for k in 1..i {
            for j in 1..i - k {
                println!("new({})", i);
                let mut sa = BitmapAlloc::new(i);
                println!("  alloc({})", k);
                let result1 = sa.alloc(k);
                assert!(result1.is_some());
                println!("  alloc({})", i - k - j);
                let result2 = sa.alloc((i - k - j));
                assert!(result2.is_some());
                println!("  alloc({})", j);
                let result3 = sa.alloc((j));
                assert!(result3.is_some());
            }
        }
    }
}

#[test]
fn allocate_deallocate_two1() {
    for i in 1..50 {
        for k in 1..i {
            println!("new({})", i);
            let mut sa = BitmapAlloc::new(i);
            println!("  alloc({})", k);
            let result1 = sa.alloc(k);
            assert!(result1.is_some());
            println!("  alloc({})", i - k);
            let result2 = sa.alloc((i - k));
            assert!(result2.is_some());

            println!("  dealloc(result1)");
            sa.dealloc_relaxed(result1.unwrap().0);
            println!("  dealloc(result2)");
            sa.dealloc_relaxed(result2.unwrap().0);
        }
    }
}

#[test]
fn stress() {
    let mut sa = BitmapAlloc::new(1000);
    let mut allocated = Vec::new();
    let mut r = Xorshift32(0x11451419u32);
    for _ in 0..1000 {
        let len = 1u32 + (r.next() & 127u32);
        println!("alloc({})", len);
        let reg = sa.alloc(len as usize);
        if let Some((reg, pos)) = reg {
            println!("  success: {:?}", (&reg, pos));
            allocated.push(reg);
        } else {
            assert!(allocated.len() > 0);
            let a_index = r.next_range(0..allocated.len() as u32);
            let old_reg = allocated.swap_remove(a_index as usize);
            println!("  failed, deallocating {:?}", old_reg);
            sa.dealloc_relaxed(old_reg);
        }
    }
    for reg in allocated {
        println!("dealloc({:?})", reg);
        sa.dealloc_relaxed(reg);
    }

    // Try the full allocation
    println!("alloc({})", 1000u32);
    let reg = sa.alloc(1000);
    assert!(reg.is_some());
}
<commit_msg>Remove unnecessary parenthesis<commit_after>//
// Copyright 2017 yvt, all rights reserved.
//
// Licensed under the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>. This file may
// not be copied, modified,or distributed except
// according to those terms.
//
extern crate xalloc;

use xalloc::BitmapAlloc;
use std::ops;

struct Xorshift32(u32);

impl Xorshift32 {
    /// Returns a random integer in `[0, 0xfffffffe]`
    fn next(&mut self) -> u32 {
        self.0 ^= self.0 << 13;
        self.0 ^= self.0 >> 17;
        self.0 ^= self.0 << 5;
        !self.0
    }
    fn next_range(&mut self, range: ops::Range<u32>) -> u32 {
        let len = range.end - range.start;
        let mut mask = len - 1;
        mask |= mask >> 1;
        mask |= mask >> 2;
        mask |= mask >> 4;
        mask |= mask >> 8;
        mask |= mask >> 16;

        // Let's not care about the unbounded execution time :)
        let mut value = self.next() & mask;
        while value >= len {
            value = self.next() & mask;
        }

        value + range.start
    }
}

#[test]
fn create() {
    for i in 1..100 {
        println!("new({})", i);
        BitmapAlloc::new(i);
    }
}

#[test]
fn full_allocate() {
    for i in 1..100 {
        println!("new({})", i);
        let mut sa = BitmapAlloc::new(i);
        let result = sa.alloc(i);
        assert!(result.is_some());
    }
}

#[test]
fn allocate_two() {
    for i in 1..50 {
        for k in 1..i {
            println!("new({})", i);
            let mut sa = BitmapAlloc::new(i);
            println!("  alloc({})", k);
            let result1 = sa.alloc(k);
            assert!(result1.is_some());
            println!("  alloc({})", i - k);
            let result2 = sa.alloc(i - k);
            assert!(result2.is_some());
        }
    }
}

#[test]
fn allocate_three() {
    for i in 1..50 {
        for k in 1..i {
            for j in 1..i - k {
                println!("new({})", i);
                let mut sa = BitmapAlloc::new(i);
                println!("  alloc({})", k);
                let result1 = sa.alloc(k);
                assert!(result1.is_some());
                println!("  alloc({})", i - k - j);
                let result2 = sa.alloc(i - k - j);
                assert!(result2.is_some());
                println!("  alloc({})", j);
                let result3 = sa.alloc(j);
                assert!(result3.is_some());
            }
        }
    }
}

#[test]
fn allocate_deallocate_two1() {
    for i in 1..50 {
        for k in 1..i {
            println!("new({})", i);
            let mut sa = BitmapAlloc::new(i);
            println!("  alloc({})", k);
            let result1 = sa.alloc(k);
            assert!(result1.is_some());
            println!("  alloc({})", i - k);
            let result2 = sa.alloc(i - k);
            assert!(result2.is_some());

            println!("  dealloc(result1)");
            sa.dealloc_relaxed(result1.unwrap().0);
            println!("  dealloc(result2)");
            sa.dealloc_relaxed(result2.unwrap().0);
        }
    }
}

#[test]
fn stress() {
    let mut sa = BitmapAlloc::new(1000);
    let mut allocated = Vec::new();
    let mut r = Xorshift32(0x11451419u32);
    for _ in 0..1000 {
        let len = 1u32 + (r.next() & 127u32);
        println!("alloc({})", len);
        let reg = sa.alloc(len as usize);
        if let Some((reg, pos)) = reg {
            println!("  success: {:?}", (&reg, pos));
            allocated.push(reg);
        } else {
            assert!(allocated.len() > 0);
            let a_index = r.next_range(0..allocated.len() as u32);
            let old_reg = allocated.swap_remove(a_index as usize);
            println!("  failed, deallocating {:?}", old_reg);
            sa.dealloc_relaxed(old_reg);
        }
    }
    for reg in allocated {
        println!("dealloc({:?})", reg);
        sa.dealloc_relaxed(reg);
    }

    // Try the full allocation
    println!("alloc({})", 1000u32);
    let reg = sa.alloc(1000);
    assert!(reg.is_some());
}
<|endoftext|>


<commit_before>use neb::server::*;
use neb::ram::schema::*;
use neb::ram::types::*;
use neb::ram::cell::*;
use neb::client;
use neb::client::transaction::TxnError;
use std::thread;
use std::sync::Arc;
use env_logger;

use super::*;

#[test]
pub fn general() {
    let server_addr = String::from("127.0.0.1:5400");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    let client = Arc::new(client::Client::new(
        &server.rpc, &vec!(server_addr),
        &String::from("test")).unwrap());
    client.new_schema(&mut schema).unwrap();
    let mut data_map = Map::<String, Value>::new();
    data_map.insert(String::from("id"), Value::I64(100));
    data_map.insert(String::from("score"), Value::U64(0));
    data_map.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map.clone());
    client.write_cell(&cell_1).unwrap().unwrap();
    client.read_cell(&cell_1.id()).unwrap().unwrap();
    client.transaction(|ref mut trans| {
        Ok(()) // empty transaction
    }).unwrap();
    let should_aborted = client.transaction(|ref mut trans| {
        trans.abort()
    });
    match should_aborted {
        Err(TxnError::Aborted) => {},
        _ => panic!("{:?}", should_aborted)
    }
    let cell_1_id = cell_1.id();
    let thread_count = 100;
    let mut threads: Vec<thread::JoinHandle<()>> = Vec::with_capacity(thread_count);
    for _ in 0..thread_count {
        let client = client.clone();
        threads.push(thread::spawn(move || {
            client.transaction(|ref mut txn| {
                let mut cell = txn.read(&cell_1_id)?.unwrap();
                let mut score = cell.data.Map().unwrap().get("score").unwrap().U64().unwrap();
                score += 1;
                let mut data = cell.data.Map().unwrap().clone();
                data.insert(String::from("score"), Value::U64(score));
                cell.data = Value::Map(data);
                txn.update(&cell)?;
                Ok(())
            }).unwrap();
        }));
    }
    for handle in threads {
        handle.join();
    }
    let mut cell_1_r = client.read_cell(&cell_1.id()).unwrap().unwrap();
    assert_eq!(cell_1_r.data.Map().unwrap().get("score").unwrap().U64().unwrap(), thread_count as u64);
}

#[test]
pub fn write_skew() {
    let server_addr = String::from("127.0.0.1:5401");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    let client = Arc::new(client::Client::new(
        &server.rpc, &vec!(server_addr),
        &String::from("test")).unwrap());
    let thread_count = 100;
    let mut threads: Vec<thread::JoinHandle<()>> = Vec::with_capacity(thread_count);
    client.new_schema(&mut schema).unwrap();
    let mut data_map = Map::<String, Value>::new();
    data_map.insert(String::from("id"), Value::I64(100));
    data_map.insert(String::from("score"), Value::U64(0));
    data_map.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map.clone());
    client.write_cell(&cell_1).unwrap().unwrap();
    client.read_cell(&cell_1.id()).unwrap().unwrap();
    let cell_1_id = cell_1.id();
    let mut cell_2 = cell_1.clone(); // clone one to test write skew
    cell_2.set_id(&Id::rand());
    client.write_cell(&cell_2).unwrap().unwrap();
    client.read_cell(&cell_2.id()).unwrap().unwrap();
    let cell_2_id = cell_2.id();
    threads = Vec::new();
    for i in 0..thread_count {
        let client = client.clone();
        threads.push(thread::spawn(move || {
            client.transaction(|ref mut txn| {
                let cell_1_id = if i % 2 == 1 {&cell_1_id} else {&cell_2_id};
                let cell_2_id = if i % 2 == 0 {&cell_1_id} else {&cell_2_id};
                let mut cell_1 = txn.read(cell_1_id)?.unwrap();
                let mut cell_2 = txn.read(cell_2_id)?.unwrap();
                let mut score = cell_1.data.Map().unwrap().get("score").unwrap().U64().unwrap();
                score += 1;
                let mut data = cell_1.data.Map().unwrap().clone();
                data.insert(String::from("score"), Value::U64(score));
                cell_1.data = Value::Map(data);
                cell_1.set_id(cell_2_id);
                cell_2.set_id(cell_1_id);
                txn.update(&cell_1)?;
                txn.update(&cell_2)?;
                Ok(())
            }).unwrap();
        }));
    }
    for handle in threads {
        handle.join();
    }
    let mut cell_1_r = client.read_cell(&cell_1_id).unwrap().unwrap();
    let mut cell_2_r = client.read_cell(&cell_2_id).unwrap().unwrap();
    assert_eq!(
        cell_1_r.data.Map().unwrap().get("score").unwrap().U64().unwrap() +
        cell_2_r.data.Map().unwrap().get("score").unwrap().U64().unwrap()
    , thread_count as u64);
}<commit_msg>isolation test seems failed<commit_after>use neb::server::*;
use neb::ram::schema::*;
use neb::ram::types::*;
use neb::ram::cell::*;
use neb::client;
use neb::client::transaction::TxnError;
use std::thread;
use std::sync::Arc;
use env_logger;

use super::*;

#[test]
pub fn general() {
    let server_addr = String::from("127.0.0.1:5400");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    let client = Arc::new(client::Client::new(
        &server.rpc, &vec!(server_addr),
        &String::from("test")).unwrap());
    client.new_schema(&mut schema).unwrap();
    let mut data_map = Map::<String, Value>::new();
    data_map.insert(String::from("id"), Value::I64(100));
    data_map.insert(String::from("score"), Value::U64(0));
    data_map.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map.clone());
    client.write_cell(&cell_1).unwrap().unwrap();
    client.read_cell(&cell_1.id()).unwrap().unwrap();
    client.transaction(|ref mut trans| {
        Ok(()) // empty transaction
    }).unwrap();
    let should_aborted = client.transaction(|ref mut trans| {
        trans.abort()
    });
    match should_aborted {
        Err(TxnError::Aborted) => {},
        _ => panic!("{:?}", should_aborted)
    }
    let cell_1_id = cell_1.id();
    let thread_count = 100;
    let mut threads: Vec<thread::JoinHandle<()>> = Vec::with_capacity(thread_count);
    for _ in 0..thread_count {
        let client = client.clone();
        threads.push(thread::spawn(move || {
            client.transaction(|ref mut txn| {
                let mut cell = txn.read(&cell_1_id)?.unwrap();
                let mut score = cell.data.Map().unwrap().get("score").unwrap().U64().unwrap();
                score += 1;
                let mut data = cell.data.Map().unwrap().clone();
                data.insert(String::from("score"), Value::U64(score));
                cell.data = Value::Map(data);
                txn.update(&cell)?;
                Ok(())
            }).unwrap();
        }));
    }
    for handle in threads {
        handle.join();
    }
    let mut cell_1_r = client.read_cell(&cell_1.id()).unwrap().unwrap();
    assert_eq!(cell_1_r.data.Map().unwrap().get("score").unwrap().U64().unwrap(), thread_count as u64);
}

#[test]
pub fn write_skew() {
    let server_addr = String::from("127.0.0.1:5401");
    let server = NebServer::new(ServerOptions {
        chunk_count: 1,
        memory_size: 16 * 1024 * 1024,
        standalone: false,
        is_meta: true,
        meta_members: vec!(server_addr.clone()),
        address: server_addr.clone(),
        backup_storage: None,
        meta_storage: None,
        group_name: String::from("test"),
    }).unwrap();
    let mut schema = Schema {
        id: 1,
        name: String::from("test"),
        key_field: None,
        fields: default_fields()
    };
    let client = Arc::new(client::Client::new(
        &server.rpc, &vec!(server_addr),
        &String::from("test")).unwrap());
    let thread_count = 100;
    let mut threads: Vec<thread::JoinHandle<()>> = Vec::with_capacity(thread_count);
    client.new_schema(&mut schema).unwrap();
    let mut data_map = Map::<String, Value>::new();
    data_map.insert(String::from("id"), Value::I64(100));
    data_map.insert(String::from("score"), Value::U64(0));
    data_map.insert(String::from("name"), Value::String(String::from("Jack")));
    let cell_1 = Cell::new(schema.id, &Id::rand(), data_map.clone());
    client.write_cell(&cell_1).unwrap().unwrap();
    client.read_cell(&cell_1.id()).unwrap().unwrap();
    let cell_1_id = cell_1.id();
    let mut cell_2 = cell_1.clone(); // clone one to test write skew
    cell_2.set_id(&Id::rand());
    client.write_cell(&cell_2).unwrap().unwrap();
    client.read_cell(&cell_2.id()).unwrap().unwrap();
    let cell_2_id = cell_2.id();
    threads = Vec::new();
    for i in 0..thread_count {
        let client = client.clone();
        threads.push(thread::spawn(move || {
            client.transaction(|ref mut txn| {
                let cell_1_id = if i % 2 == 1 {&cell_1_id} else {&cell_2_id};
                let cell_2_id = if i % 2 == 0 {&cell_1_id} else {&cell_2_id};
                let mut cell_1 = txn.read(cell_1_id)?.unwrap();
                let mut cell_2 = txn.read(cell_2_id)?.unwrap();
                let mut score = cell_1.data.Map().unwrap().get("score").unwrap().U64().unwrap();
                score += 1;
                let mut data = cell_1.data.Map().unwrap().clone();
                data.insert(String::from("score"), Value::U64(score));
                cell_1.data = Value::Map(data);
                txn.update(&cell_1)?;
                txn.update(&cell_2)?;
                Ok(())
            }).unwrap();
        }));
    }
    for handle in threads {
        handle.join();
    }
    let mut cell_1_r = client.read_cell(&cell_1_id).unwrap().unwrap();
    let mut cell_2_r = client.read_cell(&cell_2_id).unwrap().unwrap();
    let cell_1_score = cell_1_r.data.Map().unwrap().get("score").unwrap().U64().unwrap();
    let cell_2_score = cell_2_r.data.Map().unwrap().get("score").unwrap().U64().unwrap();
    println!("{} / {}", cell_1_score, cell_2_score);
    assert_eq!(cell_1_score + cell_2_score, thread_count as u64);
}<|endoftext|>


<commit_before>extern crate klee;

#[test]
fn basic_test() {
  let a : i32 = 0;
  klee::symbol(&a, "a");
  assert_eq!(a, 56);
}

#[test]
fn other_test() {
  let a : i32 = 0;
  let b : i32 = 0;

  klee::symbol(&a, "a");
  klee::symbol(&b, "b");

  if a == 50 {
    if b == 49 {
      panic!("bugger");
    }
  }
}

#[test]
fn yant() {
  let a = klee::bool("a");
  let b = klee::int("b");
  let c = if a {
    if b > 50 && b < 100 {
      true
    } else {
      false
    }
  } else {
    true
  }

  assert_eq!(c, false);
}

#[test]
fn another_test() {
  let a = klee::i32("a");
  if a > 60 && a < 90 {
    let b = a + 40;
    assert_eq!(b, 0);

    if b == 12 {
      panic!("This path should be unreachable");
    }

    assert_eq!(b, 101);
    assert_eq!(b, 150000);
  }
}
<commit_msg>Update simple.rs<commit_after>extern crate klee;

#[test]
fn basic_test() {
  let a : i32 = 0;
  klee::symbol(&a, "a");
  assert_eq!(a, 56);
}

#[test]
fn other_test() {
  let a : i32 = 0;
  let b : i32 = 0;

  klee::symbol(&a, "a");
  klee::symbol(&b, "b");

  if a == 50 {
    if b == 49 {
      panic!("bugger");
    }
  }
}

#[test]
fn yant() {
  let a = klee::bool("a");
  let b = klee::int("b");

  let c = if a {
    if b > 50 && b < 100 {
      true
    } else {
      false
    }
  } else {
    true
  };

  assert_eq!(c, false);
}

#[test]
fn another_test() {
  let a = klee::i32("a");
  if a > 60 && a < 90 {
    let b = a + 40;
    assert_eq!(b, 0);

    if b == 12 {
      panic!("This path should be unreachable");
    }

    assert_eq!(b, 101);
    assert_eq!(b, 150000);
  }
}
<|endoftext|>


<commit_before>extern crate crossbeam;
extern crate clap;
#[macro_use] extern crate version;
#[macro_use] extern crate log;
extern crate walkdir;

extern crate libimagrt;

use std::env;
use std::process::exit;
use std::process::Command;
use std::process::Stdio;
use std::io::ErrorKind;

use walkdir::WalkDir;
use crossbeam::*;
use clap::{Arg, App, AppSettings, SubCommand};

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;

fn help(cmds: Vec<String>) {
    println!(r#"

     _
    (_)_ __ ___   __ _  __ _
    | | '_ \` _ \/ _\`|/ _\`|
    | | | | | | | (_| | (_| |
    |_|_| |_| |_|\__,_|\__, |
                       |___/
    -------------------------

    Usage: imag [--version | --versions | -h | --help] <command> <args...>

    imag - the personal information management suite for the commandline

    imag is a PIM suite for the commandline. It consists of several commands,
    called "modules". Each module implements one PIM aspect and all of these
    modules can be used independently.

    Available commands:
    "#);

    for cmd in cmds.iter() {
        println!("\t{}", cmd);
    }

    println!(r#"

    Call a command with 'imag <command> <args>'
    Each command can be called with "--help" to get the respective helptext.

    Please visit https://github.com/matthiasbeyer/imag to view the source code,
    follow the development of imag or maybe even contribute to imag.

    imag is free software. It is released under the terms of LGPLv2.1

    (c) 2016 Matthias Beyer and contributors"#);
}

fn get_commands() -> Vec<String> {
    let path = env::var("PATH");
    if path.is_err() {
        println!("PATH error: {:?}", path);
        exit(1);
    }
    let pathelements = path.unwrap();
    let pathelements = pathelements.split(":");

    let joinhandles : Vec<ScopedJoinHandle<Vec<String>>> = pathelements
        .map(|elem| {
            crossbeam::scope(|scope| {
                scope.spawn(|| {
                    WalkDir::new(elem)
                        .max_depth(1)
                        .into_iter()
                        .filter(|path| {
                            match path {
                                &Ok(ref p) => p.file_name()
                                    .to_str()
                                    .map_or(false, |filename| filename.starts_with("imag-")),
                                &Err(_)   => false,
                            }
                        })
                        .filter_map(|x| x.ok())
                        .filter_map(|path| {
                           path.file_name()
                               .to_str()
                               .and_then(|s| s.splitn(2, "-").nth(1).map(String::from))
                        })
                        .collect()
                })
            })
        })
        .collect();

    let mut execs = vec![];
    for joinhandle in joinhandles.into_iter() {
        let mut v = joinhandle.join();
        execs.append(&mut v);
    }

    execs
}

pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
    app
        .settings(&[AppSettings::AllowExternalSubcommands])
        .arg(Arg::with_name("version")
             .long("version")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Get the version of imag"))
        .arg(Arg::with_name("versions")
             .long("versions")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Get the versions of the imag commands"))
        .arg(Arg::with_name("help")
             .long("help")
             .short("h")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Show help"))
        .subcommand(SubCommand::with_name("help").help("Show help"))
        .subcommands(get_commands()
            .iter()
            .map(|cmd| SubCommand::with_name(cmd))
        )
}

fn main() {
    let appname  = "imag";
    let version  = &version!();
    let about    = "imag - the PIM suite for the commandline";
    let rt       = generate_runtime_setup(appname, version, about, build_ui);
    let matches  = rt.cli();

    debug!("matches: {:?}", matches);
    if matches.is_present("help") {
        debug!("Calling help()");
        help(get_commands());
        exit(0);
    }

    if matches.is_present("version") {
        debug!("Showing version");
        println!("imag {}", &version!()[..]);
        exit(0);
    }

    if matches.is_present("versions") {
        debug!("Showing versions");
        let mut result = vec![];
        for command in get_commands().iter() {
            result.push(crossbeam::scope(|scope| {
                scope.spawn(|| {
                    let v = Command::new(command).arg("--version").output();
                    match v {
                        Ok(v) => match String::from_utf8(v.stdout) {
                            Ok(s) => format!("{} -> {}", command, s),
                            Err(e) => format!("Failed calling {} -> {:?}", command, e),
                        },
                        Err(e) => format!("Failed calling {} -> {:?}", command, e),
                    }
                })
            }))
        }

        for versionstring in result.into_iter().map(|handle| handle.join()) {
            println!("{}", versionstring);
        }
    }

    match matches.subcommand() {
        (subcommand, Some(scmd)) => {
            let subcommand_args : Vec<&str> = scmd.values_of(subcommand).unwrap().collect();
            debug!("Calling 'imag-{}' with args: {:?}", subcommand, subcommand_args);

            match Command::new(format!("imag-{}", subcommand))
                .stdin(Stdio::inherit())
                .stdout(Stdio::inherit())
                .stderr(Stdio::inherit())
                .args(&subcommand_args[..])
                .spawn()
                .and_then(|mut handle| handle.wait())
            {
                Ok(exit_status) => {
                    if !exit_status.success() {
                        debug!("{} exited with non-zero exit code: {:?}", subcommand, exit_status);
                        println!("{} exited with non-zero exit code", subcommand);
                        exit(exit_status.code().unwrap_or(42));
                    }
                    debug!("Successful exit!");
                },

                Err(e) => {
                    debug!("Error calling the subcommand");
                    match e.kind() {
                        ErrorKind::NotFound => {
                            println!("No such command: 'imag-{}'", subcommand);
                            exit(2);
                        },
                        ErrorKind::PermissionDenied => {
                            println!("No permission to execute: 'imag-{}'", subcommand);
                            exit(1);
                        },
                        _ => {
                            println!("Error spawning: {:?}", e);
                            exit(1337);
                        }
                    }
                }
            }
        },
        // clap ensures we have valid input by exiting if not.
        // The above case is a catch-all for subcommands,
        // so nothing else needs to be expexted.
        _ => unreachable!(),
    }
}
<commit_msg>Fix clap for external subcommands<commit_after>extern crate crossbeam;
extern crate clap;
#[macro_use] extern crate version;
#[macro_use] extern crate log;
extern crate walkdir;

extern crate libimagrt;

use std::env;
use std::process::exit;
use std::process::Command;
use std::process::Stdio;
use std::io::ErrorKind;

use walkdir::WalkDir;
use crossbeam::*;
use clap::{Arg, App, AppSettings, SubCommand};

use libimagrt::runtime::Runtime;
use libimagrt::setup::generate_runtime_setup;

fn help(cmds: Vec<String>) {
    println!(r#"

     _
    (_)_ __ ___   __ _  __ _
    | | '_ \` _ \/ _\`|/ _\`|
    | | | | | | | (_| | (_| |
    |_|_| |_| |_|\__,_|\__, |
                       |___/
    -------------------------

    Usage: imag [--version | --versions | -h | --help] <command> <args...>

    imag - the personal information management suite for the commandline

    imag is a PIM suite for the commandline. It consists of several commands,
    called "modules". Each module implements one PIM aspect and all of these
    modules can be used independently.

    Available commands:
    "#);

    for cmd in cmds.iter() {
        println!("\t{}", cmd);
    }

    println!(r#"

    Call a command with 'imag <command> <args>'
    Each command can be called with "--help" to get the respective helptext.

    Please visit https://github.com/matthiasbeyer/imag to view the source code,
    follow the development of imag or maybe even contribute to imag.

    imag is free software. It is released under the terms of LGPLv2.1

    (c) 2016 Matthias Beyer and contributors"#);
}

fn get_commands() -> Vec<String> {
    let path = env::var("PATH");
    if path.is_err() {
        println!("PATH error: {:?}", path);
        exit(1);
    }
    let pathelements = path.unwrap();
    let pathelements = pathelements.split(":");

    let joinhandles : Vec<ScopedJoinHandle<Vec<String>>> = pathelements
        .map(|elem| {
            crossbeam::scope(|scope| {
                scope.spawn(|| {
                    WalkDir::new(elem)
                        .max_depth(1)
                        .into_iter()
                        .filter(|path| {
                            match path {
                                &Ok(ref p) => p.file_name()
                                    .to_str()
                                    .map_or(false, |filename| filename.starts_with("imag-")),
                                &Err(_)   => false,
                            }
                        })
                        .filter_map(|x| x.ok())
                        .filter_map(|path| {
                           path.file_name()
                               .to_str()
                               .and_then(|s| s.splitn(2, "-").nth(1).map(String::from))
                        })
                        .collect()
                })
            })
        })
        .collect();

    let mut execs = vec![];
    for joinhandle in joinhandles.into_iter() {
        let mut v = joinhandle.join();
        execs.append(&mut v);
    }

    execs
}

pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
    app
        .settings(&[AppSettings::AllowExternalSubcommands])
        .arg(Arg::with_name("version")
             .long("version")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Get the version of imag"))
        .arg(Arg::with_name("versions")
             .long("versions")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Get the versions of the imag commands"))
        .arg(Arg::with_name("help")
             .long("help")
             .short("h")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Show help"))
        .subcommand(SubCommand::with_name("help").help("Show help"))
}

fn main() {
    let appname  = "imag";
    let version  = &version!();
    let about    = "imag - the PIM suite for the commandline";
    let rt       = generate_runtime_setup(appname, version, about, build_ui);
    let matches  = rt.cli();

    debug!("matches: {:?}", matches);
    if matches.is_present("help") {
        debug!("Calling help()");
        help(get_commands());
        exit(0);
    }

    if matches.is_present("version") {
        debug!("Showing version");
        println!("imag {}", &version!()[..]);
        exit(0);
    }

    if matches.is_present("versions") {
        debug!("Showing versions");
        let mut result = vec![];
        for command in get_commands().iter() {
            result.push(crossbeam::scope(|scope| {
                scope.spawn(|| {
                    let v = Command::new(command).arg("--version").output();
                    match v {
                        Ok(v) => match String::from_utf8(v.stdout) {
                            Ok(s) => format!("{} -> {}", command, s),
                            Err(e) => format!("Failed calling {} -> {:?}", command, e),
                        },
                        Err(e) => format!("Failed calling {} -> {:?}", command, e),
                    }
                })
            }))
        }

        for versionstring in result.into_iter().map(|handle| handle.join()) {
            println!("{}", versionstring);
        }
    }

    match matches.subcommand() {
        (subcommand, Some(scmd)) => {
            let subcommand_args : Vec<&str> = scmd.values_of("").unwrap().collect();
            debug!("Calling 'imag-{}' with args: {:?}", subcommand, subcommand_args);

            match Command::new(format!("imag-{}", subcommand))
                .stdin(Stdio::inherit())
                .stdout(Stdio::inherit())
                .stderr(Stdio::inherit())
                .args(&subcommand_args[..])
                .spawn()
                .and_then(|mut handle| handle.wait())
            {
                Ok(exit_status) => {
                    if !exit_status.success() {
                        debug!("{} exited with non-zero exit code: {:?}", subcommand, exit_status);
                        println!("{} exited with non-zero exit code", subcommand);
                        exit(exit_status.code().unwrap_or(42));
                    }
                    debug!("Successful exit!");
                },

                Err(e) => {
                    debug!("Error calling the subcommand");
                    match e.kind() {
                        ErrorKind::NotFound => {
                            println!("No such command: 'imag-{}'", subcommand);
                            println!("See 'imag --help' for available subcommands");
                            exit(2);
                        },
                        ErrorKind::PermissionDenied => {
                            println!("No permission to execute: 'imag-{}'", subcommand);
                            exit(1);
                        },
                        _ => {
                            println!("Error spawning: {:?}", e);
                            exit(1337);
                        }
                    }
                }
            }
        },
        // clap ensures we have valid input by exiting if not.
        // The above case is a catch-all for subcommands,
        // so nothing else needs to be expexted.
        _ => unreachable!(),
    }
}
<|endoftext|>


<commit_before>use crate::stream::Stream;

use core::marker::PhantomData;
use core::pin::Pin;
use core::task::{Context, Poll};

/// Stream for the [`pending`] function.
#[derive(Debug)]
#[must_use = "streams do nothing unless polled"]
pub struct Pending<T>(PhantomData<T>);

impl<T> Unpin for Pending<T> {}

/// Creates a stream that is never ready
///
/// The returned stream is never ready. Attempting to call
/// [`next()`](crate::stream::StreamExt::next) will never complete. Use
/// [`stream::empty()`](super::empty()) to obtain a stream that is is
/// immediately empty but returns no values.
///
/// # Examples
///
/// Basic usage:
///
/// ```no_run
/// use tokio::stream::{self, StreamExt};
///
/// #[tokio::main]
/// async fn main() {
///     let mut never = stream::empty::<i32>();
///
///     // This will never complete
///     never.next().await;
///
///     unreachable!();
/// }
/// ```
pub const fn pending<T>() -> Pending<T> {
    Pending(PhantomData)
}

impl<T> Stream for Pending<T> {
    type Item = T;

    fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Option<T>> {
        Poll::Pending
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, None)
    }
}
<commit_msg>docs: fix `stream::pending()` example (#2189)<commit_after>use crate::stream::Stream;

use core::marker::PhantomData;
use core::pin::Pin;
use core::task::{Context, Poll};

/// Stream for the [`pending`] function.
#[derive(Debug)]
#[must_use = "streams do nothing unless polled"]
pub struct Pending<T>(PhantomData<T>);

impl<T> Unpin for Pending<T> {}

/// Creates a stream that is never ready
///
/// The returned stream is never ready. Attempting to call
/// [`next()`](crate::stream::StreamExt::next) will never complete. Use
/// [`stream::empty()`](super::empty()) to obtain a stream that is is
/// immediately empty but returns no values.
///
/// # Examples
///
/// Basic usage:
///
/// ```no_run
/// use tokio::stream::{self, StreamExt};
///
/// #[tokio::main]
/// async fn main() {
///     let mut never = stream::pending::<i32>();
///
///     // This will never complete
///     never.next().await;
///
///     unreachable!();
/// }
/// ```
pub const fn pending<T>() -> Pending<T> {
    Pending(PhantomData)
}

impl<T> Stream for Pending<T> {
    type Item = T;

    fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Option<T>> {
        Poll::Pending
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, None)
    }
}
<|endoftext|>