<commit_before>extern crate mio;
extern crate regex;

#[cfg(test)]
mod tests;

pub mod route;
pub mod request;
pub mod response;

use std::io::Result;
use std::io::prelude::*;
use std::net::ToSocketAddrs;
use std::collections::HashMap;
use mio::tcp::{TcpListener, TcpStream};
use mio::util::Slab;
use mio::*;

use route::*;
use request::*;
use response::*;

struct Client {
    sock:   TcpStream,
    token:  Token,
    events: EventSet,
    i_buf:  Vec<u8>,
    o_buf:  Vec<u8>,
}

impl Client {
    fn new(sock: TcpStream, token: Token) -> Client {
        Client {
            sock:   sock,
            token:  token,
            events: EventSet::hup(),
            i_buf:  Vec::new(),
            o_buf:  Vec::new(),
        }
    }

    fn readable(&mut self) -> Result<bool> {
        let mut buf: Vec<u8> = Vec::with_capacity(2048);

        match self.sock.try_read_buf(&mut buf) {
            Ok(size)  => {
                match size {
                    Some(sz) => {
                        println!("read {} ({}) bytes", sz, buf.len());
                        self.events.remove(EventSet::readable());
                        self.events.insert(EventSet::writable());
                        self.i_buf.extend(buf);
                        return Ok(true);
                    },
                    None     => {
                        return Ok(false);
                    },
                }
            },
            Err(e)  => {
                panic!("failed to read from socket! <token: {:?}> <error: {:?}>", self.token, e);
            },
        }

        Ok(false)
    }

    /* write the client's output buffer to the socket.
     *
     * the following return values mean:
     *  - Ok(true):  we can close the connection
     *  - Ok(false): keep listening for writeable event and continue next time
     *  - Err(e):    something dun fucked up
     */
    fn writable(&mut self) -> Result<bool> {
        let tmp = self.o_buf.clone();
        let out = tmp.as_slice();
        match self.sock.write(&out) {
            Ok(sz)  => {
                if sz == self.o_buf.len() {
                    /* we did it! */
                    self.events.remove(EventSet::writable());
                    return Ok(true);
                } else {
                    let tmp: Vec<u8> = self.o_buf.split_off(sz);
                    println!("{:?}, -{}, {:?}", out, sz, tmp);
                    self.o_buf = tmp;

                    return Ok(false);
                }
            },
            Err(e)  => {
                panic!("failed to write to socket! <token: {:?}> <error: {:?}>", self.token, e);
            }
        }

        Ok(false)
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        self.events.insert(EventSet::readable());

        evl.register(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.reregister(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to re-register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }
}

/* our primary object. similar interface to Flask, the
 * Python microframework. much faster, however! :)
 */
pub struct Canteen {
    routes:  HashMap<String, Route>,
    server:  TcpListener,
    token:   Token,
    conns:   Slab<Client>,
    default: fn(&Request) -> Response,
}

impl Handler for Canteen {
    type Timeout = ();
    type Message = u32;

    fn ready(&mut self, evl: &mut EventLoop<Canteen>, token: Token, events: EventSet) {
        if events.is_error() || events.is_hup() {
            self.reset_connection(token);
            return;
        }

        if events.is_readable() {
            if self.token == token {
                self.accept(evl);
            } else {
                self.readable(evl, token)
                    .and_then(|_| self.get_client(token)
                                      .reregister(evl))
                    .unwrap_or_else(|e| {
                        panic!("read event failed! <token: {:?}> <error: {:?}>", token, e);
                    });
            }

            return;
        }

        if events.is_writable() {
            match self.get_client(token).writable() {
                Ok(true)    => { self.reset_connection(token); },
                Ok(false)   => { let _ = self.get_client(token).reregister(evl); },
                Err(_)      => { panic!("something really bad happened!"); },
            }
        }
    }
}

impl Canteen {
    pub fn new<A: ToSocketAddrs>(addr: A) -> Canteen {
        Canteen {
            routes:  HashMap::new(),
            server:  TcpListener::bind(&addr.to_socket_addrs().unwrap().next().unwrap()).unwrap(),
            token:   Token(1),
            conns:   Slab::new_starting_at(Token(2), 2048),
            default: Route::err_404,
        }
    }

    pub fn add_route(&mut self, path: &str, mlist: Vec<Method>, handler: fn(&Request) -> Response) {
        let pc = String::from(path);

        if self.routes.contains_key(&pc) {
            panic!("a route handler for {} has already been defined!", path);
        }

        self.routes.insert(String::from(path), Route::new(&path, mlist, handler));
    }

    pub fn set_default(&mut self, handler: fn(&Request) -> Response) {
        self.default = handler;
    }

    fn get_client<'a>(&'a mut self, token: Token) -> &'a mut Client {
        &mut self.conns[token]
    }

    fn accept(&mut self, evl: &mut EventLoop<Canteen>) {
        let (sock, _) = match self.server.accept() {
            Ok(s)   => {
                match s {
                    Some(sock)  => sock,
                    None        => {
                        panic!("failed to accept new connection!");
                    }
                }
            },
            Err(e)  => {
                panic!("failed to accept new connection! <error: {:?}>", e);
            },
        };

        match self.conns.insert_with(|token| Client::new(sock, token)) {
            Some(token) => {
                match self.get_client(token).register(evl) {
                    Ok(_)   => {},
                    Err(e)  => {
                        panic!("failed to register client! <token: {:?}> <error: {:?}>", token, e);
                    },
                }
            },
            None        => {
                panic!("failed to add client connection!");
            },
        }

        self.reregister(evl);
    }

    fn handle_request(&self, req: &Request) -> Vec<u8> {
        let mut handler: fn(&Request) -> Response = self.default;

        for (_, route) in &self.routes {
            match (route).is_match(req) {
                true  => { handler = route.handler; break; },
                false => continue,
            }
        }

        handler(req).gen_output()
    }

    fn readable(&mut self, evl: &mut EventLoop<Canteen>, token: Token) -> Result<bool> {
        match self.get_client(token).readable() {
            Ok(true)    => {
                let buf = self.get_client(token).i_buf.clone();
                let rqstr = String::from_utf8(buf).unwrap();
                let mut req = Request::from_str(&rqstr);
                let output = self.handle_request(&mut req);

                self.get_client(token).o_buf.extend(output);
            },
            Ok(false)   => {},
            Err(e)      => {
                panic!("message wasn't actually readable! <error: {:?}>", e);
            },
        };

        let _ = self.get_client(token).reregister(evl);

        Ok(true)
    }

    fn reset_connection(&mut self, token: Token) {
        /* kill the connection */
        self.conns.remove(token);
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.register(&self.server, self.token, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) {
        match evl.reregister(&self.server, self.token,
                             EventSet::readable(),
                             PollOpt::edge() | PollOpt::oneshot()) {
            Ok(_)   => {},
            Err(e)  => {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           }
        };
    }

    pub fn run(&mut self) {
        let mut evl = EventLoop::new().unwrap();
        self.register(&mut evl).ok();
        evl.run(self).unwrap();
    }
}
<commit_msg>minor tweaks<commit_after>extern crate mio;
extern crate regex;

#[cfg(test)]
mod tests;

pub mod route;
pub mod request;
pub mod response;

use std::io::Result;
use std::io::prelude::*;
use std::net::ToSocketAddrs;
use std::collections::HashMap;
use mio::tcp::{TcpListener, TcpStream};
use mio::util::Slab;
use mio::*;

use route::*;
use request::*;
use response::*;

struct Client {
    sock:   TcpStream,
    token:  Token,
    events: EventSet,
    i_buf:  Vec<u8>,
    o_buf:  Vec<u8>,
}

impl Client {
    fn new(sock: TcpStream, token: Token) -> Client {
        Client {
            sock:   sock,
            token:  token,
            events: EventSet::hup(),
            i_buf:  Vec::new(),
            o_buf:  Vec::new(),
        }
    }

    fn readable(&mut self) -> Result<bool> {
        let mut buf: Vec<u8> = Vec::with_capacity(2048);

        match self.sock.try_read_buf(&mut buf) {
            Ok(size)  => {
                match size {
                    Some(sz) => {
                        println!("read {} ({}) bytes", sz, buf.len());
                        self.events.remove(EventSet::readable());
                        self.events.insert(EventSet::writable());
                        self.i_buf.extend(buf);
                        return Ok(true);
                    },
                    None     => {
                        return Ok(false);
                    },
                }
            },
            Err(e)  => {
                panic!("failed to read from socket! <token: {:?}> <error: {:?}>", self.token, e);
            },
        }

        Ok(false)
    }

    /* write the client's output buffer to the socket.
     *
     * the following return values mean:
     *  - Ok(true):  we can close the connection
     *  - Ok(false): keep listening for writeable event and continue next time
     *  - Err(e):    something dun fucked up
     */
    fn writable(&mut self) -> Result<bool> {
        let tmp = self.o_buf.clone();
        let out = tmp.as_slice();
        match self.sock.write(&out) {
            Ok(sz)  => {
                if sz == self.o_buf.len() {
                    /* we did it! */
                    self.events.remove(EventSet::writable());
                    return Ok(true);
                } else {
                    let tmp: Vec<u8> = self.o_buf.split_off(sz);
                    println!("{:?}, -{}, {:?}", out, sz, tmp);
                    self.o_buf = tmp;

                    return Ok(false);
                }
            },
            Err(e)  => {
                panic!("failed to write to socket! <token: {:?}> <error: {:?}>", self.token, e);
            }
        }

        Ok(false)
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        self.events.insert(EventSet::readable());

        evl.register(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.reregister(&self.sock, self.token, self.events, PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to re-register client! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }
}

/* our primary object. similar interface to Flask, the
 * Python microframework. much faster, however! :)
 */
pub struct Canteen {
    routes:  HashMap<String, Route>,
    server:  TcpListener,
    token:   Token,
    conns:   Slab<Client>,
    default: fn(&Request) -> Response,
}

impl Handler for Canteen {
    type Timeout = ();
    type Message = u32;

    fn ready(&mut self, evl: &mut EventLoop<Canteen>, token: Token, events: EventSet) {
        if events.is_error() || events.is_hup() {
            self.reset_connection(token);
            return;
        }

        if events.is_readable() {
            if self.token == token {
                self.accept(evl);
            } else {
                self.readable(evl, token)
                    .and_then(|_| self.get_client(token)
                                      .reregister(evl))
                    .unwrap_or_else(|e| {
                        panic!("read event failed! <token: {:?}> <error: {:?}>", token, e);
                    });
            }

            return;
        }

        if events.is_writable() {
            match self.get_client(token).writable() {
                Ok(true)    => { self.reset_connection(token); },
                Ok(false)   => { let _ = self.get_client(token).reregister(evl); },
                Err(_)      => { panic!("something really bad happened!"); },
            }
        }
    }
}

impl Canteen {
    pub fn new<A: ToSocketAddrs>(addr: A) -> Canteen {
        Canteen {
            routes:  HashMap::new(),
            server:  TcpListener::bind(&addr.to_socket_addrs().unwrap().next().unwrap()).unwrap(),
            token:   Token(1),
            conns:   Slab::new_starting_at(Token(2), 2048),
            default: Route::err_404,
        }
    }

    pub fn add_route(&mut self, path: &str, mlist: Vec<Method>, handler: fn(&Request) -> Response) {
        let pc = String::from(path);

        if self.routes.contains_key(&pc) {
            panic!("a route handler for {} has already been defined!", path);
        }

        self.routes.insert(String::from(path), Route::new(&path, mlist, handler));
    }

    pub fn set_default(&mut self, handler: fn(&Request) -> Response) {
        self.default = handler;
    }

    fn get_client<'a>(&'a mut self, token: Token) -> &'a mut Client {
        &mut self.conns[token]
    }

    fn accept(&mut self, evl: &mut EventLoop<Canteen>) {
        let (sock, _) = match self.server.accept() {
            Ok(s)   => {
                match s {
                    Some(sock)  => sock,
                    None        => {
                        panic!("failed to accept new connection!");
                    }
                }
            },
            Err(e)  => {
                panic!("failed to accept new connection! <error: {:?}>", e);
            },
        };

        match self.conns.insert_with(|token| Client::new(sock, token)) {
            Some(token) => {
                match self.get_client(token).register(evl) {
                    Ok(_)   => {},
                    Err(e)  => {
                        panic!("failed to register client! <token: {:?}> <error: {:?}>", token, e);
                    },
                }
            },
            None        => {
                panic!("failed to add client connection!");
            },
        }

        self.reregister(evl);
    }

    fn handle_request(&self, req: &mut Request) -> Vec<u8> {
        let mut handler: fn(&Request) -> Response = self.default;

        for (_, route) in &self.routes {
            match (route).is_match(req) {
                true  => {
                    handler = route.handler;
                    req.params = route.parse(&req.path);
                    break;
                },
                false => continue,
            }
        }

        handler(req).gen_output()
    }

    fn readable(&mut self, evl: &mut EventLoop<Canteen>, token: Token) -> Result<bool> {
        match self.get_client(token).readable() {
            Ok(true)    => {
                let buf = self.get_client(token).i_buf.clone();
                let rqstr = String::from_utf8(buf).unwrap();
                let mut req = Request::from_str(&rqstr);
                let output = self.handle_request(&mut req);

                self.get_client(token).o_buf.extend(output);
            },
            Ok(false)   => {},
            Err(e)      => {
                panic!("message wasn't actually readable! <error: {:?}>", e);
            },
        };

        let _ = self.get_client(token).reregister(evl);

        Ok(true)
    }

    fn reset_connection(&mut self, token: Token) {
        /* kill the connection */
        self.conns.remove(token);
    }

    fn register(&mut self, evl: &mut EventLoop<Canteen>) -> Result<()> {
        evl.register(&self.server, self.token, EventSet::readable(), PollOpt::edge() | PollOpt::oneshot())
           .or_else(|e| {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           })
    }

    fn reregister(&mut self, evl: &mut EventLoop<Canteen>) {
        match evl.reregister(&self.server, self.token,
                             EventSet::readable(),
                             PollOpt::edge() | PollOpt::oneshot()) {
            Ok(_)   => {},
            Err(e)  => {
               panic!("failed to register server! <token: {:?}> <error: {:?}>", self.token, e);
           }
        };
    }

    pub fn run(&mut self) {
        let mut evl = EventLoop::new().unwrap();
        self.register(&mut evl).ok();
        evl.run(self).unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate portmidi as pm;

extern crate rustc_serialize;
extern crate docopt;

const USAGE: &'static str = r#"
portmidi-rs: monitor-device example

Usage:
    monitor-device <id>

Options:
    -h --help   Show this screen.

Omitting <id> will list the available devices.
"#;

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_id: i32,
}

fn print_devices(pm: &pm::PortMidi) {
    for dev in pm.devices().unwrap() {
        println!("{}", dev);
    }
}

fn main() {
    let context = pm::PortMidi::new(1024).unwrap();
    let args: Args = docopt::Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|err| {
        print_devices(&context);
        err.exit();
    });
    let info = context.device(args.arg_id).unwrap();
    println!("Listening on: {}) {}", info.id(), info.name());

    let mut in_port = context.input_port(info).unwrap();
    while let Ok(_) = in_port.poll() {
        if let Ok(Some(event)) = in_port.read_n(1024) {
            println!("{:?}", event);
        }
    }
}
<commit_msg>Fix the monitor example<commit_after>extern crate portmidi as pm;

extern crate rustc_serialize;
extern crate docopt;

const USAGE: &'static str = r#"
portmidi-rs: monitor-device example

Usage:
    monitor-device <id>

Options:
    -h --help   Show this screen.

Omitting <id> will list the available devices.
"#;

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_id: i32,
}

fn print_devices(pm: &pm::PortMidi) {
    for dev in pm.devices().unwrap() {
        println!("{}", dev);
    }
}

fn main() {
    // initialize the PortMidi context.
    let context = pm::PortMidi::new().unwrap();

    // setup the command line interface
    let args: Args = docopt::Docopt::new(USAGE).and_then(|d| d.decode()).unwrap_or_else(|err| {
        print_devices(&context);
        err.exit();
    });

    // get the device info for the given id
    let info = context.device(args.arg_id).unwrap();
    println!("Listening on: {}) {}", info.id(), info.name());

    // get the device's input port
    let mut in_port = context.input_port(info, 1024).unwrap();

    while let Ok(_) = in_port.poll() {
        if let Ok(Some(event)) = in_port.read_n(1024) {
            println!("{:?}", event);
            // there is no blocking receive method in PortMidi, therefore
            // we have to sleep some time to prevent a busy-wait loop
            ::std::thread::sleep_ms(20);
        }
    }
}
<|endoftext|>


<commit_before>use object::read::archive::ArchiveFile;
use object::read::macho::{FatArch, FatHeader};
use object::{Object, ObjectComdat, ObjectSection, ObjectSymbol};
use std::{env, fs, process};

fn main() {
    let arg_len = env::args().len();
    if arg_len <= 1 {
        eprintln!("Usage: {} <file> ...", env::args().next().unwrap());
        process::exit(1);
    }

    for file_path in env::args().skip(1) {
        if arg_len > 2 {
            println!();
            println!("{}:", file_path);
        }

        let file = match fs::File::open(&file_path) {
            Ok(file) => file,
            Err(err) => {
                println!("Failed to open file '{}': {}", file_path, err,);
                continue;
            }
        };
        let file = match unsafe { memmap2::Mmap::map(&file) } {
            Ok(mmap) => mmap,
            Err(err) => {
                println!("Failed to map file '{}': {}", file_path, err,);
                continue;
            }
        };

        if let Ok(archive) = ArchiveFile::parse(&*file) {
            println!("Format: Archive (kind: {:?})", archive.kind());
            for member in archive.members() {
                if let Ok(member) = member {
                    println!();
                    println!("{}:", String::from_utf8_lossy(member.name()));
                    if let Ok(data) = member.data(&*file) {
                        dump_object(data);
                    }
                }
            }
        } else if let Ok(arches) = FatHeader::parse_arch32(&*file) {
            println!("Format: Mach-O Fat 32");
            for arch in arches {
                println!();
                println!("Fat Arch: {:?}", arch.architecture());
                if let Ok(data) = arch.data(&*file) {
                    dump_object(data);
                }
            }
        } else if let Ok(arches) = FatHeader::parse_arch64(&*file) {
            println!("Format: Mach-O Fat 64");
            for arch in arches {
                println!();
                println!("Fat Arch: {:?}", arch.architecture());
                if let Ok(data) = arch.data(&*file) {
                    dump_object(data);
                }
            }
        } else {
            dump_object(&*file);
        }
    }
}

fn dump_object(data: &[u8]) {
    let file = match object::File::parse(data) {
        Ok(file) => file,
        Err(err) => {
            println!("Failed to parse file: {}", err);
            return;
        }
    };
    println!(
        "Format: {:?} {:?}-endian {}-bit",
        file.format(),
        file.endianness(),
        if file.is_64() { "64" } else { "32" }
    );
    println!("Architecture: {:?}", file.architecture());
    println!("Flags: {:x?}", file.flags());

    match file.mach_uuid() {
        Ok(Some(uuid)) => println!("Mach UUID: {:x?}", uuid),
        Ok(None) => {}
        Err(e) => println!("Failed to parse Mach UUID: {}", e),
    }
    match file.build_id() {
        Ok(Some(build_id)) => println!("Build ID: {:x?}", build_id),
        Ok(None) => {}
        Err(e) => println!("Failed to parse build ID: {}", e),
    }
    match file.gnu_debuglink() {
        Ok(Some((filename, crc))) => println!(
            "GNU debug link: {} CRC: {:08x}",
            String::from_utf8_lossy(filename),
            crc,
        ),
        Ok(None) => {}
        Err(e) => println!("Failed to parse GNU debug link: {}", e),
    }
    match file.gnu_debugaltlink() {
        Ok(Some((filename, build_id))) => println!(
            "GNU debug alt link: {}, build ID: {:x?}",
            String::from_utf8_lossy(filename),
            build_id,
        ),
        Ok(None) => {}
        Err(e) => println!("Failed to parse GNU debug alt link: {}", e),
    }
    match file.pdb_info() {
        Ok(Some(info)) => println!(
            "PDB file: {}, GUID: {:x?}, Age: {}",
            String::from_utf8_lossy(info.path()),
            info.guid(),
            info.age()
        ),
        Ok(None) => {}
        Err(e) => println!("Failed to parse PE CodeView info: {}", e),
    }

    for segment in file.segments() {
        println!("{:x?}", segment);
    }

    for section in file.sections() {
        println!("{}: {:x?}", section.index().0, section);
    }

    for comdat in file.comdats() {
        print!("{:?} Sections:", comdat);
        for section in comdat.sections() {
            print!(" {}", section.0);
        }
        println!();
    }

    println!();
    println!("Symbols");
    for symbol in file.symbols() {
        println!("{}: {:x?}", symbol.index().0, symbol);
    }

    for section in file.sections() {
        if section.relocations().next().is_some() {
            println!(
                "\n{} relocations",
                section.name().unwrap_or("<invalid name>")
            );
            for relocation in section.relocations() {
                println!("{:x?}", relocation);
            }
        }
    }

    println!();
    println!("Dynamic symbols");
    for symbol in file.dynamic_symbols() {
        println!("{}: {:x?}", symbol.index().0, symbol);
    }

    if let Some(relocations) = file.dynamic_relocations() {
        println!();
        println!("Dynamic relocations");
        for relocation in relocations {
            println!("{:x?}", relocation);
        }
    }

    let imports = file.imports().unwrap();
    if !imports.is_empty() {
        println!();
        for import in imports {
            println!("{:?}", import);
        }
    }

    let exports = file.exports().unwrap();
    if !exports.is_empty() {
        println!();
        for export in exports {
            println!("{:x?}", export);
        }
    }
}
<commit_msg>objdump: allow selecting members from containers<commit_after>use object::read::archive::ArchiveFile;
use object::read::macho::{FatArch, FatHeader};
use object::{Object, ObjectComdat, ObjectSection, ObjectSymbol};
use std::{env, fs, process};

fn main() {
    let mut args = env::args();
    let cmd = args.next().unwrap();
    if args.len() == 0 {
        eprintln!("Usage: {} <file> [<member>...]", cmd);
        process::exit(1);
    }
    let file_path = args.next().unwrap();
    let mut member_names: Vec<_> = args.map(|name| (name, false)).collect();

    let file = match fs::File::open(&file_path) {
        Ok(file) => file,
        Err(err) => {
            eprintln!("Failed to open file '{}': {}", file_path, err,);
            process::exit(1);
        }
    };
    let file = match unsafe { memmap2::Mmap::map(&file) } {
        Ok(mmap) => mmap,
        Err(err) => {
            eprintln!("Failed to map file '{}': {}", file_path, err,);
            process::exit(1);
        }
    };

    if let Ok(archive) = ArchiveFile::parse(&*file) {
        eprintln!("Format: Archive (kind: {:?})", archive.kind());
        for member in archive.members() {
            if let Ok(member) = member {
                if find_member(&mut member_names, member.name()) {
                    println!();
                    println!("{}:", String::from_utf8_lossy(member.name()));
                    if let Ok(data) = member.data(&*file) {
                        dump_object(data);
                    }
                }
            }
        }
    } else if let Ok(arches) = FatHeader::parse_arch32(&*file) {
        println!("Format: Mach-O Fat 32");
        for arch in arches {
            println!();
            println!("Fat Arch: {:?}", arch.architecture());
            if let Ok(data) = arch.data(&*file) {
                dump_object(data);
            }
        }
    } else if let Ok(arches) = FatHeader::parse_arch64(&*file) {
        println!("Format: Mach-O Fat 64");
        for arch in arches {
            println!();
            println!("Fat Arch: {:?}", arch.architecture());
            if let Ok(data) = arch.data(&*file) {
                dump_object(data);
            }
        }
    } else {
        dump_object(&*file);
    }

    for (name, found) in member_names {
        if !found {
            eprintln!("Failed to find member '{}", name);
        }
    }
}

fn find_member(member_names: &mut [(String, bool)], name: &[u8]) -> bool {
    if member_names.is_empty() {
        return true;
    }
    match member_names.iter().position(|x| x.0.as_bytes() == name) {
        Some(i) => {
            member_names[i].1 = true;
            true
        }
        None => false,
    }
}

fn dump_object(data: &[u8]) {
    let file = match object::File::parse(data) {
        Ok(file) => file,
        Err(err) => {
            println!("Failed to parse file: {}", err);
            return;
        }
    };
    println!(
        "Format: {:?} {:?}-endian {}-bit",
        file.format(),
        file.endianness(),
        if file.is_64() { "64" } else { "32" }
    );
    println!("Architecture: {:?}", file.architecture());
    println!("Flags: {:x?}", file.flags());

    match file.mach_uuid() {
        Ok(Some(uuid)) => println!("Mach UUID: {:x?}", uuid),
        Ok(None) => {}
        Err(e) => println!("Failed to parse Mach UUID: {}", e),
    }
    match file.build_id() {
        Ok(Some(build_id)) => println!("Build ID: {:x?}", build_id),
        Ok(None) => {}
        Err(e) => println!("Failed to parse build ID: {}", e),
    }
    match file.gnu_debuglink() {
        Ok(Some((filename, crc))) => println!(
            "GNU debug link: {} CRC: {:08x}",
            String::from_utf8_lossy(filename),
            crc,
        ),
        Ok(None) => {}
        Err(e) => println!("Failed to parse GNU debug link: {}", e),
    }
    match file.gnu_debugaltlink() {
        Ok(Some((filename, build_id))) => println!(
            "GNU debug alt link: {}, build ID: {:x?}",
            String::from_utf8_lossy(filename),
            build_id,
        ),
        Ok(None) => {}
        Err(e) => println!("Failed to parse GNU debug alt link: {}", e),
    }
    match file.pdb_info() {
        Ok(Some(info)) => println!(
            "PDB file: {}, GUID: {:x?}, Age: {}",
            String::from_utf8_lossy(info.path()),
            info.guid(),
            info.age()
        ),
        Ok(None) => {}
        Err(e) => println!("Failed to parse PE CodeView info: {}", e),
    }

    for segment in file.segments() {
        println!("{:x?}", segment);
    }

    for section in file.sections() {
        println!("{}: {:x?}", section.index().0, section);
    }

    for comdat in file.comdats() {
        print!("{:?} Sections:", comdat);
        for section in comdat.sections() {
            print!(" {}", section.0);
        }
        println!();
    }

    println!();
    println!("Symbols");
    for symbol in file.symbols() {
        println!("{}: {:x?}", symbol.index().0, symbol);
    }

    for section in file.sections() {
        if section.relocations().next().is_some() {
            println!(
                "\n{} relocations",
                section.name().unwrap_or("<invalid name>")
            );
            for relocation in section.relocations() {
                println!("{:x?}", relocation);
            }
        }
    }

    println!();
    println!("Dynamic symbols");
    for symbol in file.dynamic_symbols() {
        println!("{}: {:x?}", symbol.index().0, symbol);
    }

    if let Some(relocations) = file.dynamic_relocations() {
        println!();
        println!("Dynamic relocations");
        for relocation in relocations {
            println!("{:x?}", relocation);
        }
    }

    let imports = file.imports().unwrap();
    if !imports.is_empty() {
        println!();
        for import in imports {
            println!("{:?}", import);
        }
    }

    let exports = file.exports().unwrap();
    if !exports.is_empty() {
        println!();
        for export in exports {
            println!("{:x?}", export);
        }
    }
}
<|endoftext|>


<commit_before>use primal_bit::{BitVec};
use std::{cmp};
use hamming;

use wheel;
use primal_smallsieve::Primes;

/// A segmented sieve that yields only a small run of primes at a
/// time.
///
/// This is heavily inspired by this [segmented
/// sieve](http://primesieve.org/segmented_sieve.html) code.
#[derive(Debug)]
pub struct StreamingSieve {
    small: Primes,
    // stores which numbers *aren't* prime, i.e. true == composite.
    sieve: BitVec,
    primes: Vec<wheel::WheelInfo<wheel::Wheel210>>,
    small_primes: Vec<wheel::WheelInfo<wheel::Wheel30>>,
    presieve: BitVec,

    low: usize,
    current: usize,
    limit: usize,
}

const CACHE: usize = (32 << 10);
const SEG_ELEMS: usize = 8 * CACHE;
const SEG_LEN: usize = SEG_ELEMS * wheel::BYTE_MODULO / wheel::BYTE_SIZE;

const PRESIEVE_PROD: usize = 2 * 3 * 5 * 7 * 11 * 13;
const PRESIEVE_PRIMES: &'static [usize] = &[2, 3, 5, 7, 11, 13];
const PRESIEVE_NEXT: usize = 17;
const PRESIEVE_ACTIVE: bool = true;

fn bits_for(x: usize) -> usize {
    (x * wheel::BYTE_SIZE + wheel::BYTE_MODULO - 1) / wheel::BYTE_MODULO
}

#[inline(never)]
fn compute_presieve(limit_bits: usize) -> BitVec {
    assert!(PRESIEVE_ACTIVE);
    let len = cmp::min(bits_for(PRESIEVE_PROD),
                       limit_bits);
    let mut bitv = BitVec::from_elem(len, false);

    // this is silly and should be done with a sieve that only uses
    // the primes in PRESIEVE_PRIMES.
    for i in 0..len {
        let true_ = wheel::from_bit_index(i);
        fn gcd(x: usize, y: usize) -> usize {
            if y == 0 { x }
            else { gcd(y, x % y) }
        }
        if gcd(true_, PRESIEVE_PROD) != 1 {
            bitv.set(i, true)
        }
    }
    bitv
}

impl StreamingSieve {
    /// Create a new instance of the streaming sieve that will
    /// correctly progressively filter primes up to `limit`.
    pub fn new(limit: usize) -> StreamingSieve {
        let small = Primes::sieve((limit as f64).sqrt() as usize + 1);
        let current = PRESIEVE_NEXT;
        let low = 0;

        let elems = cmp::min(bits_for(limit), SEG_ELEMS);
        let presieve = compute_presieve(elems);

        StreamingSieve {
            small: small,
            sieve: BitVec::from_elem(elems, false),
            primes: vec![],
            small_primes: vec![],
            presieve: presieve,

            low: low,
            current: current,
            limit: limit
        }
    }
    fn split_index(&self, idx: usize) -> (usize, usize) {
        let len = SEG_ELEMS;
        (idx / len,idx % len)
    }
    fn index_for(&self, n: usize) -> (bool, usize, usize) {
        let (b, idx) = wheel::bit_index(n);
        let (base, tweak) = self.split_index(idx);
        (b, base, tweak)
    }

    pub fn count_upto(n: usize) -> usize {
        match n {
            0...1 => 0,
            2 => 1,
            3...4 => 2,
            5...6 => 3,
            7...10 => 4,
            _ => {
                let mut sieve = StreamingSieve::new(n);
                let (includes, base, tweak) = sieve.index_for(n);
                let mut count = match wheel::BYTE_MODULO {
                    30 => 3,
                    _ => unimplemented!()
                };

                for _ in 0..base {
                    let (_, bitv) = sieve.next().unwrap();
                    let bytes = bitv.as_bytes();
                    count += 8 * bytes.len() - hamming::weight(bytes) as usize;
                }
                let (tweak_byte, tweak_bit) = (tweak / 8, tweak % 8);
                let (_, last) = sieve.next().unwrap();
                let bytes = last.as_bytes();
                count += 8 * tweak_byte - hamming::weight(&bytes[..tweak_byte]) as usize;
                let byte = bytes[tweak_byte];
                for i in 0..tweak_bit + includes as usize {
                    count += (byte & (1 << i) == 0) as usize
                }
                count
            }
        }
    }

    pub fn very_small_sieve(&mut self, low: usize) {
        let offset = (low % PRESIEVE_PROD) * wheel::BYTE_SIZE / wheel::BYTE_MODULO / 8;

        copy_all(self.sieve.as_bytes_mut(),
                 self.presieve.as_bytes(),
                 offset);
        fn copy_all(mut dst: &mut [u8], src: &[u8], init_offset: usize) {
            let mut pos = 0;
            // pre-fill data at the start, as a rotation of `src`.
            pos += memcpy(&mut dst[pos..], &src[init_offset..]);
            if pos >= dst.len() { return }

            pos += memcpy(&mut dst[pos..], &src[..init_offset]);
            if pos >= dst.len() { return }

            // progressively copy the prefix to the rest of the
            // vector, doubling each time.
            while pos < dst.len() {
                let (filled, unfilled) = dst.split_at_mut(pos);
                pos += memcpy(unfilled, filled);
            }
        }
        fn memcpy<'d>(dst: &'d mut [u8], src: &[u8]) -> usize {
            use std::ptr;
            let l = cmp::min(dst.len(), src.len());
            unsafe {
                ptr::copy(src.as_ptr(), dst.as_mut_ptr(), l);
            }
            l
        }
    }

    fn small_primes_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();
        for wi in &mut self.small_primes {
            wi.sieve_hardcoded(bytes);
        }
    }

    fn direct_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();

        let mut iter = self.primes.iter_mut();

        while iter.size_hint().0 >= 2 {
            match (iter.next(), iter.next()) {
                (Some(wi1), Some(wi2)) => {
                    wi1.sieve_pair(wi2, bytes);
                }
                _ => unreachable!()
            }
        }
        for wi in iter {
            wi.sieve(bytes)
        }
    }

    /// Extract the next chunk of filtered primes, the return value is
    /// `Some((low, v))` or `None` if the sieve has reached the limit.
    ///
    /// The vector stores bits for each odd number starting at `low`.
    /// Bit `n` of `v` is set if and only if `low + 2 * n + 1` is
    /// prime.
    ///
    /// NB. the prime 2 is not included in any of these sieves and so
    /// needs special handling.
    pub fn next(&mut self) -> Option<(usize, &BitVec)> {
        if self.low >= self.limit {
            return None
        }

        let low = self.low;
        self.low += SEG_LEN;
        let high = cmp::min(low + SEG_LEN - 1, self.limit);
        self.sieve.clear();

        let mut s = self.current;

        while s * s <= high {
            if self.small.is_prime(s) {
                if s <= SEG_LEN / 100 {
                    self.small_primes.push(wheel::compute_wheel_elem(wheel::Wheel30, s, low));
                } else {
                    self.primes.push(wheel::compute_wheel_elem(wheel::Wheel210, s, low));
                }
            }
            s += 1
        }

        self.current = s;
        if PRESIEVE_ACTIVE && self.presieve.len() > 0 {
            self.very_small_sieve(low);
        }
        self.small_primes_sieve();
        self.direct_sieve();

        if low == 0 {
            // 1 is not prime.
            self.sieve.set(0, true);
            if PRESIEVE_ACTIVE {
                // but these are
                for &x in PRESIEVE_PRIMES {
                    let (use_, idx) = wheel::bit_index(x);
                    if use_ {
                        self.sieve.set(idx, false)
                    }
                }
            }
        }

        Some((low, &self.sieve))
    }
}

#[cfg(test)]
mod tests {
    use wheel;
    use super::StreamingSieve;
    fn gcd(x: usize, y: usize) -> usize {
        if y == 0 { x }
        else { gcd(y, x % y) }
    }
    fn coprime_to(x: usize) -> Vec<usize> {
        (1..x).filter(|&n| gcd(n, x) == 1).collect()
    }
    #[test]
    fn test() {
        let coprime = coprime_to(wheel::BYTE_MODULO);
        const LIMIT: usize = 2_000_000;
        let mut sieve = StreamingSieve::new(LIMIT);
        let primes = ::primal_smallsieve::Primes::sieve(LIMIT);

        let mut base = 0;
        let mut index = 0;

        while let Some((_low, next)) = sieve.next() {
            for val in next {
                let i = wheel::BYTE_MODULO * base + coprime[index];
                if i >= LIMIT { break }
                assert!(primes.is_prime(i) == !val,
                        "failed for {} (is prime = {})", i, primes.is_prime(i));

                index += 1;
                if index == wheel::BYTE_SIZE {
                    index = 0;
                    base += 1
                }
            }
        }
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use test::Bencher;
    use super::StreamingSieve;

    fn run(b: &mut Bencher, n: usize) {
        b.iter(|| {
            let mut sieve = StreamingSieve::new(n);
            while sieve.next().is_some() {}
        })
    }

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        run(b, 100)
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        run(b, 10_000)
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        run(b, 100_000)
    }
    #[bench]
    fn sieve_larger(b: &mut Bencher) {
        run(b, 1_000_000)
    }
    #[bench]
    fn sieve_huge(b: &mut Bencher) {
        run(b, 10_000_000)
    }
}
<commit_msg>sieve: add presieving benchmarks.<commit_after>use primal_bit::{BitVec};
use std::{cmp};
use hamming;

use wheel;
use primal_smallsieve::Primes;

/// A segmented sieve that yields only a small run of primes at a
/// time.
///
/// This is heavily inspired by this [segmented
/// sieve](http://primesieve.org/segmented_sieve.html) code.
#[derive(Debug)]
pub struct StreamingSieve {
    small: Primes,
    // stores which numbers *aren't* prime, i.e. true == composite.
    sieve: BitVec,
    primes: Vec<wheel::WheelInfo<wheel::Wheel210>>,
    small_primes: Vec<wheel::WheelInfo<wheel::Wheel30>>,
    presieve: BitVec,

    low: usize,
    current: usize,
    limit: usize,
}

const CACHE: usize = (32 << 10);
const SEG_ELEMS: usize = 8 * CACHE;
const SEG_LEN: usize = SEG_ELEMS * wheel::BYTE_MODULO / wheel::BYTE_SIZE;

const PRESIEVE_PROD: usize = 2 * 3 * 5 * 7 * 11 * 13;
const PRESIEVE_PRIMES: &'static [usize] = &[2, 3, 5, 7, 11, 13];
const PRESIEVE_NEXT: usize = 17;
const PRESIEVE_ACTIVE: bool = true;

fn bits_for(x: usize) -> usize {
    (x * wheel::BYTE_SIZE + wheel::BYTE_MODULO - 1) / wheel::BYTE_MODULO
}

#[inline(never)]
fn compute_presieve(limit_bits: usize) -> BitVec {
    assert!(PRESIEVE_ACTIVE);
    let len = cmp::min(bits_for(PRESIEVE_PROD),
                       limit_bits);
    let mut bitv = BitVec::from_elem(len, false);

    // this is silly and should be done with a sieve that only uses
    // the primes in PRESIEVE_PRIMES.
    for i in 0..len {
        let true_ = wheel::from_bit_index(i);
        fn gcd(x: usize, y: usize) -> usize {
            if y == 0 { x }
            else { gcd(y, x % y) }
        }
        if gcd(true_, PRESIEVE_PROD) != 1 {
            bitv.set(i, true)
        }
    }
    bitv
}

impl StreamingSieve {
    /// Create a new instance of the streaming sieve that will
    /// correctly progressively filter primes up to `limit`.
    pub fn new(limit: usize) -> StreamingSieve {
        let small = Primes::sieve((limit as f64).sqrt() as usize + 1);
        let current = PRESIEVE_NEXT;
        let low = 0;

        let elems = cmp::min(bits_for(limit), SEG_ELEMS);
        let presieve = compute_presieve(elems);

        StreamingSieve {
            small: small,
            sieve: BitVec::from_elem(elems, false),
            primes: vec![],
            small_primes: vec![],
            presieve: presieve,

            low: low,
            current: current,
            limit: limit
        }
    }
    fn split_index(&self, idx: usize) -> (usize, usize) {
        let len = SEG_ELEMS;
        (idx / len,idx % len)
    }
    fn index_for(&self, n: usize) -> (bool, usize, usize) {
        let (b, idx) = wheel::bit_index(n);
        let (base, tweak) = self.split_index(idx);
        (b, base, tweak)
    }

    pub fn count_upto(n: usize) -> usize {
        match n {
            0...1 => 0,
            2 => 1,
            3...4 => 2,
            5...6 => 3,
            7...10 => 4,
            _ => {
                let mut sieve = StreamingSieve::new(n);
                let (includes, base, tweak) = sieve.index_for(n);
                let mut count = match wheel::BYTE_MODULO {
                    30 => 3,
                    _ => unimplemented!()
                };

                for _ in 0..base {
                    let (_, bitv) = sieve.next().unwrap();
                    let bytes = bitv.as_bytes();
                    count += 8 * bytes.len() - hamming::weight(bytes) as usize;
                }
                let (tweak_byte, tweak_bit) = (tweak / 8, tweak % 8);
                let (_, last) = sieve.next().unwrap();
                let bytes = last.as_bytes();
                count += 8 * tweak_byte - hamming::weight(&bytes[..tweak_byte]) as usize;
                let byte = bytes[tweak_byte];
                for i in 0..tweak_bit + includes as usize {
                    count += (byte & (1 << i) == 0) as usize
                }
                count
            }
        }
    }

    pub fn very_small_sieve(&mut self, low: usize) {
        let offset = (low % PRESIEVE_PROD) * wheel::BYTE_SIZE / wheel::BYTE_MODULO / 8;

        copy_all(self.sieve.as_bytes_mut(),
                 self.presieve.as_bytes(),
                 offset);
        fn copy_all(mut dst: &mut [u8], src: &[u8], init_offset: usize) {
            let mut pos = 0;
            // pre-fill data at the start, as a rotation of `src`.
            pos += memcpy(&mut dst[pos..], &src[init_offset..]);
            if pos >= dst.len() { return }

            pos += memcpy(&mut dst[pos..], &src[..init_offset]);
            if pos >= dst.len() { return }

            // progressively copy the prefix to the rest of the
            // vector, doubling each time.
            while pos < dst.len() {
                let (filled, unfilled) = dst.split_at_mut(pos);
                pos += memcpy(unfilled, filled);
            }
        }
        fn memcpy<'d>(dst: &'d mut [u8], src: &[u8]) -> usize {
            use std::ptr;
            let l = cmp::min(dst.len(), src.len());
            unsafe {
                ptr::copy(src.as_ptr(), dst.as_mut_ptr(), l);
            }
            l
        }
    }

    fn small_primes_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();
        for wi in &mut self.small_primes {
            wi.sieve_hardcoded(bytes);
        }
    }

    fn direct_sieve(&mut self) {
        let bytes = self.sieve.as_bytes_mut();

        let mut iter = self.primes.iter_mut();

        while iter.size_hint().0 >= 2 {
            match (iter.next(), iter.next()) {
                (Some(wi1), Some(wi2)) => {
                    wi1.sieve_pair(wi2, bytes);
                }
                _ => unreachable!()
            }
        }
        for wi in iter {
            wi.sieve(bytes)
        }
    }

    /// Extract the next chunk of filtered primes, the return value is
    /// `Some((low, v))` or `None` if the sieve has reached the limit.
    ///
    /// The vector stores bits for each odd number starting at `low`.
    /// Bit `n` of `v` is set if and only if `low + 2 * n + 1` is
    /// prime.
    ///
    /// NB. the prime 2 is not included in any of these sieves and so
    /// needs special handling.
    pub fn next(&mut self) -> Option<(usize, &BitVec)> {
        if self.low >= self.limit {
            return None
        }

        let low = self.low;
        self.low += SEG_LEN;
        let high = cmp::min(low + SEG_LEN - 1, self.limit);
        self.sieve.clear();

        let mut s = self.current;

        while s * s <= high {
            if self.small.is_prime(s) {
                if s <= SEG_LEN / 100 {
                    self.small_primes.push(wheel::compute_wheel_elem(wheel::Wheel30, s, low));
                } else {
                    self.primes.push(wheel::compute_wheel_elem(wheel::Wheel210, s, low));
                }
            }
            s += 1
        }

        self.current = s;
        if PRESIEVE_ACTIVE && self.presieve.len() > 0 {
            self.very_small_sieve(low);
        }
        self.small_primes_sieve();
        self.direct_sieve();

        if low == 0 {
            // 1 is not prime.
            self.sieve.set(0, true);
            if PRESIEVE_ACTIVE {
                // but these are
                for &x in PRESIEVE_PRIMES {
                    let (use_, idx) = wheel::bit_index(x);
                    if use_ {
                        self.sieve.set(idx, false)
                    }
                }
            }
        }

        Some((low, &self.sieve))
    }
}

#[cfg(test)]
mod tests {
    use wheel;
    use super::StreamingSieve;
    fn gcd(x: usize, y: usize) -> usize {
        if y == 0 { x }
        else { gcd(y, x % y) }
    }
    fn coprime_to(x: usize) -> Vec<usize> {
        (1..x).filter(|&n| gcd(n, x) == 1).collect()
    }
    #[test]
    fn test() {
        let coprime = coprime_to(wheel::BYTE_MODULO);
        const LIMIT: usize = 2_000_000;
        let mut sieve = StreamingSieve::new(LIMIT);
        let primes = ::primal_smallsieve::Primes::sieve(LIMIT);

        let mut base = 0;
        let mut index = 0;

        while let Some((_low, next)) = sieve.next() {
            for val in next {
                let i = wheel::BYTE_MODULO * base + coprime[index];
                if i >= LIMIT { break }
                assert!(primes.is_prime(i) == !val,
                        "failed for {} (is prime = {})", i, primes.is_prime(i));

                index += 1;
                if index == wheel::BYTE_SIZE {
                    index = 0;
                    base += 1
                }
            }
        }
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use test::Bencher;
    use super::StreamingSieve;

    fn run(b: &mut Bencher, n: usize) {
        b.iter(|| {
            let mut sieve = StreamingSieve::new(n);
            while sieve.next().is_some() {}
        })
    }
    fn run_presieve(b: &mut Bencher, n: usize) {
        b.iter(|| super::compute_presieve(super::bits_for(n)))
    }

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        run(b, 100)
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        run(b, 10_000)
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        run(b, 100_000)
    }
    #[bench]
    fn sieve_larger(b: &mut Bencher) {
        run(b, 1_000_000)
    }
    #[bench]
    fn sieve_huge(b: &mut Bencher) {
        run(b, 10_000_000)
    }
    #[bench]
    fn presieve_small(b: &mut Bencher) {
        run_presieve(b, 100)
    }
    #[bench]
    fn presieve_medium(b: &mut Bencher) {
        run_presieve(b, 10_000)
    }
    #[bench]
    fn presieve_large(b: &mut Bencher) {
        run_presieve(b, 100_000)
    }
    #[bench]
    fn presieve_larger(b: &mut Bencher) {
        run_presieve(b, 1_000_000)
    }
    #[bench]
    fn presieve_huge(b: &mut Bencher) {
        run_presieve(b, 10_000_000)
    }
}
<|endoftext|>


<commit_before>//! Checks that all error codes have at least one test to prevent having error
//! codes that are silently not thrown by the compiler anymore.

use std::collections::HashMap;
use std::ffi::OsStr;
use std::path::Path;

// A few of those error codes can't be tested but all the others can and *should* be tested!
const WHITELIST: &[&str] = &[
    "E0183",
    "E0227",
    "E0279",
    "E0280",
    "E0311",
    "E0313",
    "E0314",
    "E0315",
    "E0377",
    "E0456",
    "E0461",
    "E0462",
    "E0464",
    "E0465",
    "E0472",
    "E0473",
    "E0474",
    "E0475",
    "E0476",
    "E0479",
    "E0480",
    "E0481",
    "E0482",
    "E0483",
    "E0484",
    "E0485",
    "E0486",
    "E0487",
    "E0488",
    "E0489",
    "E0514",
    "E0519",
    "E0523",
    "E0554",
    "E0570",
    "E0629",
    "E0630",
    "E0640",
    "E0717",
    "E0727",
    "E0729",
];

fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>) {
    let mut reached_no_explanation = false;
    let mut last_error_code = None;

    for line in f.lines() {
        let s = line.trim();
        if s.starts_with('E') && s.ends_with(": r##\"") {
            if let Some(err_code) = s.splitn(2, ':').next() {
                let err_code = err_code.to_owned();
                last_error_code = Some(err_code.clone());
                if !error_codes.contains_key(&err_code) {
                    error_codes.insert(err_code, false);
                }
            }
        } else if s.starts_with("```") && s.contains("compile_fail") && s.contains('E') {
            if let Some(err_code) = s.splitn(2, 'E').skip(1).next() {
                if let Some(err_code) = err_code.splitn(2, ',').next() {
                    let nb = error_codes.entry(format!("E{}", err_code)).or_insert(false);
                    *nb = true;
                }
            }
        } else if s == ";" {
            reached_no_explanation = true;
        } else if reached_no_explanation && s.starts_with('E') {
            if let Some(err_code) = s.splitn(2, ',').next() {
                let err_code = err_code.to_owned();
                if !error_codes.contains_key(&err_code) { // this check should *never* fail!
                    error_codes.insert(err_code, false);
                }
            }
        } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
            if let Some(last) = last_error_code {
                error_codes.get_mut(&last).map(|x| *x = true);
            }
            last_error_code = None;
        }
    }
}

fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap<String, bool>) {
    for line in f.lines() {
        let s = line.trim();
        if s.starts_with("error[E") || s.starts_with("warning[E") {
            if let Some(err_code) = s.splitn(2, ']').next() {
                if let Some(err_code) = err_code.splitn(2, '[').skip(1).next() {
                    let nb = error_codes.entry(err_code.to_owned()).or_insert(false);
                    *nb = true;
                }
            }
        }
    }
}

pub fn check(path: &Path, bad: &mut bool) {
    println!("Checking which error codes lack tests...");
    let mut error_codes: HashMap<String, bool> = HashMap::new();
    super::walk(path,
                &mut |path| super::filter_dirs(path),
                &mut |entry, contents| {
        let file_name = entry.file_name();
        if file_name == "error_codes.rs" {
            extract_error_codes(contents, &mut error_codes);
        } else if entry.path().extension() == Some(OsStr::new("stderr")) {
            extract_error_codes_from_tests(contents, &mut error_codes);
        }
    });
    println!("Found {} error codes", error_codes.len());

    let mut errors = Vec::new();
    for (err_code, nb) in &error_codes {
        if !*nb && !WHITELIST.contains(&err_code.as_str()) {
            errors.push(format!("Error code {} needs to have at least one UI test!", err_code));
        }
    }
    errors.sort();
    for err in &errors {
        eprintln!("{}", err);
    }
    println!("Found {} error codes with no tests", errors.len());
    if !errors.is_empty() {
        *bad = true;
    }
    println!("Done!");
}
<commit_msg>Update tidy check for error codes testing<commit_after>//! Checks that all error codes have at least one test to prevent having error
//! codes that are silently not thrown by the compiler anymore.

use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs::read_to_string;
use std::io::Read;
use std::path::Path;

// A few of those error codes can't be tested but all the others can and *should* be tested!
const WHITELIST: &[&str] = &[
    "E0183",
    "E0227",
    "E0279",
    "E0280",
    "E0311",
    "E0313",
    "E0314",
    "E0315",
    "E0377",
    "E0456",
    "E0461",
    "E0462",
    "E0464",
    "E0465",
    "E0472",
    "E0473",
    "E0474",
    "E0475",
    "E0476",
    "E0479",
    "E0480",
    "E0481",
    "E0482",
    "E0483",
    "E0484",
    "E0485",
    "E0486",
    "E0487",
    "E0488",
    "E0489",
    "E0514",
    "E0519",
    "E0523",
    "E0554",
    "E0570",
    "E0629",
    "E0630",
    "E0640",
    "E0717",
    "E0727",
    "E0729",
];

fn check_error_code_explanation(
    f: &str,
    error_codes: &mut HashMap<String, bool>,
    err_code: String,
) {
    for line in f.lines() {
        let s = line.trim();
        if s.starts_with("```") && s.contains("compile_fail") && s.contains('E') {
            error_codes.insert(err_code, true);
            return;
        } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") {
            error_codes.get_mut(&err_code).map(|x| *x = true);
            return;
        }
    }
}

macro_rules! some_or_continue {
    ($e:expr) => (
        match $e {
            Some(e) => e,
            None => continue,
        }
    );
}

fn extract_error_codes(f: &str, error_codes: &mut HashMap<String, bool>, path: &Path) {
    let mut reached_no_explanation = false;

    for line in f.lines() {
        let s = line.trim();
        if !reached_no_explanation && s.starts_with('E') && s.contains("include_str!(\"") {
            if let Some(err_code) = s.splitn(2, ':').next() {
                let err_code = err_code.to_owned();
                if !error_codes.contains_key(&err_code) {
                    error_codes.insert(err_code.clone(), false);
                }
                // Now we extract the tests from the markdown file!
                let md = some_or_continue!(s.splitn(2, "include_str!(\"").skip(1).next());
                let md_file_name = some_or_continue!(md.splitn(2, "\")").next());
                let path = some_or_continue!(path.parent()).join(md_file_name);
                match read_to_string(&path) {
                    Ok(content) => {
                        check_error_code_explanation(
                            &content,
                            error_codes,
                            err_code,
                        );
                    }
                    Err(e) => {
                        eprintln!("Couldn't read `{}`: {}", path.display(), e);
                    }
                }
            }
        } else if reached_no_explanation && s.starts_with('E') {
            if let Some(err_code) = s.splitn(2, ',').next() {
                let err_code = err_code.to_owned();
                if !error_codes.contains_key(&err_code) { // this check should *never* fail!
                    error_codes.insert(err_code, false);
                }
            }
        } else if s == ";" {
            reached_no_explanation = true;
        }
    }
}

fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap<String, bool>) {
    for line in f.lines() {
        let s = line.trim();
        if s.starts_with("error[E") || s.starts_with("warning[E") {
            if let Some(err_code) = s.splitn(2, ']').next() {
                if let Some(err_code) = err_code.splitn(2, '[').skip(1).next() {
                    let nb = error_codes.entry(err_code.to_owned()).or_insert(false);
                    *nb = true;
                }
            }
        }
    }
}

pub fn check(path: &Path, bad: &mut bool) {
    println!("Checking which error codes lack tests...");
    let mut error_codes: HashMap<String, bool> = HashMap::new();
    super::walk(path,
                &mut |path| super::filter_dirs(path),
                &mut |entry, contents| {
        let file_name = entry.file_name();
        if file_name == "error_codes.rs" {
            extract_error_codes(contents, &mut error_codes, entry.path());
        } else if entry.path().extension() == Some(OsStr::new("stderr")) {
            extract_error_codes_from_tests(contents, &mut error_codes);
        }
    });
    println!("Found {} error codes", error_codes.len());

    let mut errors = Vec::new();
    for (err_code, nb) in &error_codes {
        if !*nb && !WHITELIST.contains(&err_code.as_str()) {
            errors.push(format!("Error code {} needs to have at least one UI test!", err_code));
        }
    }
    errors.sort();
    for err in &errors {
        eprintln!("{}", err);
    }
    println!("Found {} error codes with no tests", errors.len());
    if !errors.is_empty() {
        *bad = true;
    }
    println!("Done!");
}
<|endoftext|>


<commit_before>#[macro_use]
mod common;

use common::util::*;

static UTIL_NAME: &'static str = "cat";

#[test]
fn test_output_multi_files_print_all_chars() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    ucmd.arg("alpha.txt")
        .arg("256.txt")
        .arg("-A")
        .arg("-n");

    assert_eq!(ucmd.run().stdout,
               "     1\tabcde$\n     2\tfghij$\n     3\tklmno$\n     4\tpqrst$\n     \
                5\tuvwxyz$\n     6\t^@^A^B^C^D^E^F^G^H^I$\n     \
                7\t^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\\^]^^^_ \
                !\"#$%&\'()*+,-./0123456789:;\
                <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~^?M-^@M-^AM-^\
                BM-^CM-^DM-^EM-^FM-^GM-^HM-^IM-^JM-^KM-^LM-^MM-^NM-^OM-^PM-^QM-^RM-^SM-^TM-^UM-^V\
                M-^WM-^XM-^YM-^ZM-^[M-^\\M-^]M-^^M-^_M- \
                M-!M-\"M-#M-$M-%M-&M-\'M-(M-)M-*M-+M-,M--M-.M-/M-0M-1M-2M-3M-4M-5M-6M-7M-8M-9M-:\
                M-;M-<M-=M->M-?M-@M-AM-BM-CM-DM-EM-FM-GM-HM-IM-JM-KM-LM-MM-NM-OM-PM-QM-RM-SM-TM-U\
                M-VM-WM-XM-YM-ZM-[M-\\M-]M-^M-_M-`M-aM-bM-cM-dM-eM-fM-gM-hM-iM-jM-kM-lM-mM-nM-oM-\
                pM-qM-rM-sM-tM-uM-vM-wM-xM-yM-zM-{M-|M-}M-~M-^?");
}

#[test]
fn test_stdin_squeeze() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let out = ucmd.arg("-A")
                  .run_piped_stdin("\x00\x01\x02".as_bytes())
                  .stdout;

    assert_eq!(out, "^@^A^B");
}

#[test]
fn test_stdin_number_non_blank() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let out = ucmd.arg("-b")
                  .arg("-")
                  .run_piped_stdin("\na\nb\n\n\nc".as_bytes())
                  .stdout;

    assert_eq!(out, "\n     1\ta\n     2\tb\n\n\n     3\tc");
}
<commit_msg>tests/cat: --squeeze-blank test<commit_after>#[macro_use]
mod common;

use common::util::*;

static UTIL_NAME: &'static str = "cat";

#[test]
fn test_output_multi_files_print_all_chars() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    ucmd.arg("alpha.txt")
        .arg("256.txt")
        .arg("-A")
        .arg("-n");

    assert_eq!(ucmd.run().stdout,
               "     1\tabcde$\n     2\tfghij$\n     3\tklmno$\n     4\tpqrst$\n     \
                5\tuvwxyz$\n     6\t^@^A^B^C^D^E^F^G^H^I$\n     \
                7\t^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\\^]^^^_ \
                !\"#$%&\'()*+,-./0123456789:;\
                <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~^?M-^@M-^AM-^\
                BM-^CM-^DM-^EM-^FM-^GM-^HM-^IM-^JM-^KM-^LM-^MM-^NM-^OM-^PM-^QM-^RM-^SM-^TM-^UM-^V\
                M-^WM-^XM-^YM-^ZM-^[M-^\\M-^]M-^^M-^_M- \
                M-!M-\"M-#M-$M-%M-&M-\'M-(M-)M-*M-+M-,M--M-.M-/M-0M-1M-2M-3M-4M-5M-6M-7M-8M-9M-:\
                M-;M-<M-=M->M-?M-@M-AM-BM-CM-DM-EM-FM-GM-HM-IM-JM-KM-LM-MM-NM-OM-PM-QM-RM-SM-TM-U\
                M-VM-WM-XM-YM-ZM-[M-\\M-]M-^M-_M-`M-aM-bM-cM-dM-eM-fM-gM-hM-iM-jM-kM-lM-mM-nM-oM-\
                pM-qM-rM-sM-tM-uM-vM-wM-xM-yM-zM-{M-|M-}M-~M-^?");
}

#[test]
fn test_stdin_show_all() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let out = ucmd.arg("-A")
                  .run_piped_stdin("\x00\x01\x02".as_bytes())
                  .stdout;

    assert_eq!(out, "^@^A^B");
}

#[test]
fn test_stdin_squeeze_blank() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let out = ucmd.arg("--squeeze-blank")
                  .run_piped_stdin("\n\na\n\n\n\n\nb\n\n\n".as_bytes())
                  .stdout;

    assert_eq!(out, "\na\n\nb\n\n");
}

#[test]
fn test_stdin_number_non_blank() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let out = ucmd.arg("-b")
                  .arg("-")
                  .run_piped_stdin("\na\nb\n\n\nc".as_bytes())
                  .stdout;

    assert_eq!(out, "\n     1\ta\n     2\tb\n\n\n     3\tc");
}
<|endoftext|>


<commit_before>extern crate odbc_sys;
extern crate odbc_safe;

use odbc_safe::*;

#[test]
fn allocate_environment() {
    Environment::new().unwrap();
}

#[test]
fn allocate_connection() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    Connection::with_parent(&env).unwrap();
}

#[test]
#[should_panic]
fn wrong_datasource() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    dbc.connect(b"DoesntExist" as &[u8], b"" as &[u8], b"" as &[u8])
        .unwrap();
}

#[test]
fn diagnostics() {

    let expected = if cfg!(target_os = "windows") {
        "[Microsoft][ODBC Driver Manager] Data source name not found and no default driver \
         specified"
    } else {
        "[unixODBC][Driver Manager]Data source name not found, and no default driver specified"
    };

    use std::str;

    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();

    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect(b"DoesntExist" as &[u8], b"" as &[u8], b"" as &[u8]);
    if let Error(d) = dbc {
        let mut message = [0; 512];
        match d.diagnostics(1, &mut message) {
            DiagReturn::Success(rec) => {
                let message = str::from_utf8(&mut message[..(rec.text_length as usize)]).unwrap();
                assert_eq!(expected, message);
            }
            _ => panic!("Error retriving diagnostics"),
        }
    }
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn connect_to_postgres() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect(b"PostgreSQL" as &[u8], b"postgres" as &[u8], b"" as &[u8]);
    match dbc {
        Success(c) => panic_with_diagnostic(&c.disconnect()),
        Info(c) => panic_with_diagnostic(&c),
        Error(c) => panic_with_diagnostic(&c),
    };
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn query_result() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect(b"PostgreSQL" as &[u8], b"postgres" as &[u8], b"" as &[u8])
        .unwrap();
    Statement::with_parent(&dbc).unwrap();
}

/// Checks for a diagnstic record. Should one be present this function panics printing the contents
/// of said record.
fn panic_with_diagnostic(diag: &Diagnostics) {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        DiagReturn::Success(dr) |
        DiagReturn::Info(dr) => {
            panic!(
                "{}",
                str::from_utf8(&buffer[0..(dr.text_length as usize)]).unwrap()
            )
        }
        DiagReturn::Error => panic!("Error during fetching diagnostic record"),
        DiagReturn::NoData => (),
    }
}
<commit_msg>add disconnect<commit_after>extern crate odbc_sys;
extern crate odbc_safe;

use odbc_safe::*;

#[test]
fn allocate_environment() {
    Environment::new().unwrap();
}

#[test]
fn allocate_connection() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    Connection::with_parent(&env).unwrap();
}

#[test]
#[should_panic]
fn wrong_datasource() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    dbc.connect(b"DoesntExist" as &[u8], b"" as &[u8], b"" as &[u8])
        .unwrap();
}

#[test]
fn diagnostics() {

    let expected = if cfg!(target_os = "windows") {
        "[Microsoft][ODBC Driver Manager] Data source name not found and no default driver \
         specified"
    } else {
        "[unixODBC][Driver Manager]Data source name not found, and no default driver specified"
    };

    use std::str;

    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();

    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect(b"DoesntExist" as &[u8], b"" as &[u8], b"" as &[u8]);
    if let Error(d) = dbc {
        let mut message = [0; 512];
        match d.diagnostics(1, &mut message) {
            DiagReturn::Success(rec) => {
                let message = str::from_utf8(&mut message[..(rec.text_length as usize)]).unwrap();
                assert_eq!(expected, message);
            }
            _ => panic!("Error retriving diagnostics"),
        }
    }
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn connect_to_postgres() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect(b"PostgreSQL" as &[u8], b"postgres" as &[u8], b"" as &[u8]);
    match dbc {
        Success(c) => panic_with_diagnostic(&c.disconnect()),
        Info(c) => panic_with_diagnostic(&c),
        Error(c) => panic_with_diagnostic(&c),
    };
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn query_result() {
    let env = Environment::new().unwrap();
    let env: Environment<Odbc3> = env.declare_version().unwrap();
    let dbc = Connection::with_parent(&env).unwrap();
    let dbc = dbc.connect(b"PostgreSQL" as &[u8], b"postgres" as &[u8], b"" as &[u8])
        .unwrap();
    {
        Statement::with_parent(&dbc).unwrap();
    }
    dbc.disconnect().unwrap();
}

/// Checks for a diagnstic record. Should one be present this function panics printing the contents
/// of said record.
fn panic_with_diagnostic(diag: &Diagnostics) {
    use std::str;
    let mut buffer = [0; 512];
    match diag.diagnostics(1, &mut buffer) {
        DiagReturn::Success(dr) |
        DiagReturn::Info(dr) => {
            panic!(
                "{}",
                str::from_utf8(&buffer[0..(dr.text_length as usize)]).unwrap()
            )
        }
        DiagReturn::Error => panic!("Error during fetching diagnostic record"),
        DiagReturn::NoData => (),
    }
}
<|endoftext|>


<commit_before>extern crate tvdb;
extern crate rand;

use tvdb::{Tvdb, EpisodeId, TvdbResult, TvdbError};

const APIKEY: &'static str = "0629B785CE550C8D";

#[test]
fn search() {
    let api = Tvdb::new(APIKEY.to_owned());
    let sr = api.search("scrubs", "en");
    assert!(sr.ok().unwrap()[0].seriesname == "Scrubs");
}

#[test]
fn nonexist() {
    let api = Tvdb::new(APIKEY);
    let sr = api.search("ladlkgdklfgsdfglk", "en");
    assert!(sr.is_err());
}

#[test]
fn lookup_by_epid(){
    let api = Tvdb::new(APIKEY);
    let ep = api.episode(EpisodeId::new(76156, "en"), 1, 2);
    println!("Episode: {:?}", ep);
    assert!(ep.unwrap().episode_name == "My Mentor");
}

#[test]
fn lookup_by_u32(){
    let api = Tvdb::new(APIKEY);
    let ep = api.episode(76156, 1, 2).ok().unwrap();
    assert!(ep.episode_name == "My Mentor");
}

#[test]
fn epinfo_default(){
    let api = Tvdb::new(APIKEY);
    let sr = api.search("scrubs", "en").ok().unwrap();
    let ep = api.episode(&sr[0], 1, 2).ok().unwrap();
    assert!(ep.episode_name == "My Mentor");
}

#[test]
fn random_series(){
    // Opening a bunch of ~random series to check for panicing
    use rand::{Rng, SeedableRng, StdRng};

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);
    for _ in 1..10{
        let rid = rng.gen_range::<u32>(1, 20000);
        println!("Getting series {}", rid);

        let api = Tvdb::new(APIKEY);
        let ep = api.episode(EpisodeId::new(rid, "en"), 1, 2);
        println!("{:?}", ep);
        match ep{
            Ok(ep) => println!("{}", ep.episode_name),
            Err(e) => println!("{:?}", e),
        }
    }
}

#[derive(Debug,Clone)]
struct CustomTestClient;

impl DummyRequestClient{
    pub fn new() -> CustomTestClient{
        return CustomTestClient{};
    }
}
use tvdb::RequestClient;
impl RequestClient for DummyRequestClient{
    fn get_url(&self, url: &str) -> TvdbResult<String>{
        return Err(TvdbError::CommunicationError{reason: "Fake error!".into()});
    }
}

#[test]
fn custom_http_client() {
    let c = DummyRequestClient::new();

    let mut api = Tvdb::new(APIKEY);
    api.set_http_client(&c);

    let result = api.search("scrubs", "en");
    println!("{:?}", result);
    assert!(result.is_err());
}
<commit_msg>Refactoring error in test<commit_after>extern crate tvdb;
extern crate rand;

use tvdb::{Tvdb, EpisodeId, TvdbResult, TvdbError};

const APIKEY: &'static str = "0629B785CE550C8D";

#[test]
fn search() {
    let api = Tvdb::new(APIKEY.to_owned());
    let sr = api.search("scrubs", "en");
    assert!(sr.ok().unwrap()[0].seriesname == "Scrubs");
}

#[test]
fn nonexist() {
    let api = Tvdb::new(APIKEY);
    let sr = api.search("ladlkgdklfgsdfglk", "en");
    assert!(sr.is_err());
}

#[test]
fn lookup_by_epid(){
    let api = Tvdb::new(APIKEY);
    let ep = api.episode(EpisodeId::new(76156, "en"), 1, 2);
    println!("Episode: {:?}", ep);
    assert!(ep.unwrap().episode_name == "My Mentor");
}

#[test]
fn lookup_by_u32(){
    let api = Tvdb::new(APIKEY);
    let ep = api.episode(76156, 1, 2).ok().unwrap();
    assert!(ep.episode_name == "My Mentor");
}

#[test]
fn epinfo_default(){
    let api = Tvdb::new(APIKEY);
    let sr = api.search("scrubs", "en").ok().unwrap();
    let ep = api.episode(&sr[0], 1, 2).ok().unwrap();
    assert!(ep.episode_name == "My Mentor");
}

#[test]
fn random_series(){
    // Opening a bunch of ~random series to check for panicing
    use rand::{Rng, SeedableRng, StdRng};

    let seed: &[_] = &[1, 2, 3, 4];
    let mut rng: StdRng = SeedableRng::from_seed(seed);
    for _ in 1..10{
        let rid = rng.gen_range::<u32>(1, 20000);
        println!("Getting series {}", rid);

        let api = Tvdb::new(APIKEY);
        let ep = api.episode(EpisodeId::new(rid, "en"), 1, 2);
        println!("{:?}", ep);
        match ep{
            Ok(ep) => println!("{}", ep.episode_name),
            Err(e) => println!("{:?}", e),
        }
    }
}

#[derive(Debug,Clone)]
struct DummyRequestClient;

impl DummyRequestClient{
    pub fn new() -> DummyRequestClient{
        return DummyRequestClient{};
    }
}
use tvdb::RequestClient;
impl RequestClient for DummyRequestClient{
    fn get_url(&self, url: &str) -> TvdbResult<String>{
        return Err(TvdbError::CommunicationError{reason: "Fake error!".into()});
    }
}

#[test]
fn custom_http_client() {
    let c = DummyRequestClient::new();

    let mut api = Tvdb::new(APIKEY);
    api.set_http_client(&c);

    let result = api.search("scrubs", "en");
    println!("{:?}", result);
    assert!(result.is_err());
}
<|endoftext|>


<commit_before>extern crate gradr_backend;
extern crate hyper;
extern crate github;
extern crate url;

use std::comm::sync_channel;
use std::io::timer;
use std::sync::{Arc, RWLock};
use std::time::Duration;

use gradr_backend::builder::{WholeBuildable, ToWholeBuildable};
use gradr_backend::database::Database;
use gradr_backend::database::sqlite::SqliteDatabase;
use gradr_backend::database::testing::TestDatabase;
use gradr_backend::notification_listener::{NotificationSource, GitHubServer};
use gradr_backend::notification_listener::testing::TestNotificationSource;
use gradr_backend::worker::worker_loop_step;

use self::github::server::testing::{send_to_server, SendPush};
use self::github::notification::PushNotification;

use self::url::Url;
use self::hyper::{IpAddr, Ipv4Addr, Port};

static ADDR: IpAddr = Ipv4Addr(127, 0, 0, 1);

fn end_to_end<B : WholeBuildable, E : ToWholeBuildable<B>, D : Database<E>, N : NotificationSource<E>>(
    db: D,
    not_src: N,
    to_send: Vec<E>,
    sender: |E| -> (),
    stop_all: || -> (),
    checker: |&D| -> bool) { // returns true if it expects more results

    let done1 = Arc::new(RWLock::new(false));
    let done2 = done1.clone();

    let db1 = Arc::new(db);
    let db2 = db1.clone();
    let db3 = db1.clone();

    spawn(proc() {
        while not_src.notification_event_loop_step(&*db1) {}
    });

    spawn(proc() {
        while !*done1.read() {
            worker_loop_step(&*db2);
        }
    });

    for e in to_send.into_iter() {
        sender(e);
    }

    stop_all();

    let mut success = false;

    for _ in range(0, 300u) {
        timer::sleep(Duration::milliseconds(10));
        if !checker(&*db3) {
            success = true;
            break;
        }
    }

    let mut val = done2.write();
    *val = true;
    val.downgrade();

    assert!(success);
}

fn end_to_end_test_not_source<A : Database<Path>>(db: A) {
    let (notification_sender, notification_recv) = sync_channel(10);
    let not_src = TestNotificationSource::new(notification_recv);
    let to_send = vec!(Path::new("test/end_to_end"));
    let sender = |path: Path| {
        notification_sender.send(Some(path));
    };
    let stop_all = || {
        notification_sender.send(None);
    };
    let checker = |db: &A| {
        match db.results_for_entry(Path::new("test/end_to_end")) {
            Some(ref s) => {
                assert!(s.contains("test1: Pass"));
                assert!(s.contains("test2: Fail"));
                false
            },
            None => true
        }
    };

    end_to_end(db, not_src, to_send, sender, stop_all, checker);
}

fn end_to_end_github_not_source<A : Database<PushNotification>>(db: A, port: Port) {
    let server = GitHubServer::new(ADDR, port);
    let not_src = server.event_loop().unwrap();
    let not1 =
        PushNotification {
            clone_url: Url::parse("https://github.com/scalableinternetservices/GradrBackend.git").unwrap(),
            branch: "testing".to_string()
        };

    let to_send = vec!(not1);
    let sender = |not: PushNotification| {
        send_to_server(SendPush(not).to_string().as_slice(), ADDR, port)
    };
    let stop_all = || {
        //not_src1.wrapped.send_finish()
    };
    let checker = |db: &A| {
        let not2 =
            PushNotification {
                clone_url: Url::parse("https://github.com/scalableinternetservices/GradrBackend.git").unwrap(),
                branch: "master".to_string()
            };

        match db.results_for_entry(not2) {
            Some(ref s) => {
                assert!(s.contains("test1: Pass"));
                assert!(s.contains("test2: Fail"));
                false
            },
            None => true
        }
    };

    end_to_end(db, not_src, to_send, sender, stop_all, checker);
}

#[test]
fn end_to_end_test_not_source_in_memory() {
    end_to_end_test_not_source(TestDatabase::new());
}

#[test]
fn end_to_end_test_not_source_sqlite() {
    end_to_end_test_not_source(SqliteDatabase::new().unwrap());
}

#[test]
fn end_to_end_github_not_source_in_memory() {
    end_to_end_github_not_source(TestDatabase::new());
}

#[test]
fn end_to_end_github_not_source_sqlite() {
    end_to_end_github_not_source(SqliteDatabase::new().unwrap());
}
<commit_msg>Added missing port.  Doesn't compile due to non-generic nature of test database.<commit_after>extern crate gradr_backend;
extern crate hyper;
extern crate github;
extern crate url;

use std::comm::sync_channel;
use std::io::timer;
use std::sync::{Arc, RWLock};
use std::time::Duration;

use gradr_backend::builder::{WholeBuildable, ToWholeBuildable};
use gradr_backend::database::Database;
use gradr_backend::database::sqlite::SqliteDatabase;
use gradr_backend::database::testing::TestDatabase;
use gradr_backend::notification_listener::{NotificationSource, GitHubServer};
use gradr_backend::notification_listener::testing::TestNotificationSource;
use gradr_backend::worker::worker_loop_step;

use self::github::server::testing::{send_to_server, SendPush};
use self::github::notification::PushNotification;

use self::url::Url;
use self::hyper::{IpAddr, Ipv4Addr, Port};

static ADDR: IpAddr = Ipv4Addr(127, 0, 0, 1);

fn end_to_end<B : WholeBuildable, E : ToWholeBuildable<B>, D : Database<E>, N : NotificationSource<E>>(
    db: D,
    not_src: N,
    to_send: Vec<E>,
    sender: |E| -> (),
    stop_all: || -> (),
    checker: |&D| -> bool) { // returns true if it expects more results

    let done1 = Arc::new(RWLock::new(false));
    let done2 = done1.clone();

    let db1 = Arc::new(db);
    let db2 = db1.clone();
    let db3 = db1.clone();

    spawn(proc() {
        while not_src.notification_event_loop_step(&*db1) {}
    });

    spawn(proc() {
        while !*done1.read() {
            worker_loop_step(&*db2);
        }
    });

    for e in to_send.into_iter() {
        sender(e);
    }

    stop_all();

    let mut success = false;

    for _ in range(0, 300u) {
        timer::sleep(Duration::milliseconds(10));
        if !checker(&*db3) {
            success = true;
            break;
        }
    }

    let mut val = done2.write();
    *val = true;
    val.downgrade();

    assert!(success);
}

fn end_to_end_test_not_source<A : Database<Path>>(db: A) {
    let (notification_sender, notification_recv) = sync_channel(10);
    let not_src = TestNotificationSource::new(notification_recv);
    let to_send = vec!(Path::new("test/end_to_end"));
    let sender = |path: Path| {
        notification_sender.send(Some(path));
    };
    let stop_all = || {
        notification_sender.send(None);
    };
    let checker = |db: &A| {
        match db.results_for_entry(Path::new("test/end_to_end")) {
            Some(ref s) => {
                assert!(s.contains("test1: Pass"));
                assert!(s.contains("test2: Fail"));
                false
            },
            None => true
        }
    };

    end_to_end(db, not_src, to_send, sender, stop_all, checker);
}

fn end_to_end_github_not_source<A : Database<PushNotification>>(db: A, port: Port) {
    let server = GitHubServer::new(ADDR, port);
    let not_src = server.event_loop().unwrap();
    let not1 =
        PushNotification {
            clone_url: Url::parse("https://github.com/scalableinternetservices/GradrBackend.git").unwrap(),
            branch: "testing".to_string()
        };

    let to_send = vec!(not1);
    let sender = |not: PushNotification| {
        send_to_server(SendPush(not).to_string().as_slice(), ADDR, port)
    };
    let stop_all = || {
        //not_src1.wrapped.send_finish()
    };
    let checker = |db: &A| {
        let not2 =
            PushNotification {
                clone_url: Url::parse("https://github.com/scalableinternetservices/GradrBackend.git").unwrap(),
                branch: "master".to_string()
            };

        match db.results_for_entry(not2) {
            Some(ref s) => {
                assert!(s.contains("test1: Pass"));
                assert!(s.contains("test2: Fail"));
                false
            },
            None => true
        }
    };

    end_to_end(db, not_src, to_send, sender, stop_all, checker);
}

#[test]
fn end_to_end_test_not_source_in_memory() {
    end_to_end_test_not_source(TestDatabase::new());
}

#[test]
fn end_to_end_test_not_source_sqlite() {
    end_to_end_test_not_source(SqliteDatabase::new().unwrap());
}

#[test]
fn end_to_end_github_not_source_in_memory() {
    end_to_end_github_not_source(TestDatabase::new(), 12345);
}

#[test]
fn end_to_end_github_not_source_sqlite() {
    end_to_end_github_not_source(SqliteDatabase::new().unwrap(), 12346);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;
//extern crate serialize;

use nom::{IResult,FlatMapper,Mapper,Producer,ProducerState,FileProducer};
use nom::IResult::*;

use std::str;
use std::collections::HashMap;
//use serialize::hex::ToHex;

pub trait HexDisplay {
      /// Converts the value of `self` to a hex value, returning the owned
      ///     /// string.
  fn to_hex(&self, chunk_size: usize) -> String;
}

static CHARS: &'static[u8] = b"0123456789abcdef";

impl HexDisplay for [u8] {
    fn to_hex(&self, chunk_size: usize) -> String {
      let mut v = Vec::with_capacity(self.len() * 3);
      let mut i = 0;
      for chunk in self.chunks(chunk_size) {
        let s = format!("{:08x}", i);
        let s2: &str = &s;
        for &ch in s.as_bytes().iter() {
          v.push(ch);
        }
        v.push('\t' as u8);

        i = i + chunk_size;

        for &byte in chunk {
          v.push(CHARS[(byte >> 4) as usize]);
          v.push(CHARS[(byte & 0xf) as usize]);
          v.push(' ' as u8);
        }
        if chunk_size > chunk.len() {
          for i in 0..(chunk_size - chunk.len()) {
            v.push(' ' as u8);
            v.push(' ' as u8);
            v.push(' ' as u8);
          }
        }
        v.push('\t' as u8);

        for &byte in chunk {
          if (byte >=32 && byte <= 126) || byte >= 128 {
            v.push(byte);
          } else {
            v.push('.' as u8);
          }
        }
        v.push('\n' as u8);
      }

      unsafe {
        String::from_utf8_unchecked(v)
      }
    }
}

fn mp4_box(input:&[u8]) -> IResult<&[u8], &[u8]> {

  take!(offset_parser 4);
  match offset_parser(input) {
    Done(i, offset_bytes) => {
      let offset:u32 = (offset_bytes[3] as u32) + (offset_bytes[2] as u32) * 0x100 + (offset_bytes[1] as u32) * 0x10000 + (offset_bytes[0] as u32) * 0x1000000;
      let sz: usize = offset as usize;
      if i.len() >= sz {
        return Done(&i[(sz-4)..], &i[0..(sz-4)])
      } else {
        return Incomplete(0)
      }
    },
    e => e
  }
}

#[derive(PartialEq,Eq,Debug)]
struct FileType<'a> {
  major_brand:         &'a str,
  major_brand_version: &'a [u8],
  compatible_brands:   Vec<&'a str>
}

#[derive(PartialEq,Eq,Debug)]
enum MP4Box<'a> {
  Ftyp(FileType<'a>),
  Moov,
  Free
}

take!(offset 4);
tag!(ftyp    "ftyp".as_bytes());

fn brand_name(input:&[u8]) -> IResult<&[u8],&str> {
  take!(major_brand_bytes 4);
  major_brand_bytes(input).map_res(str::from_utf8)
}
take!(major_brand_version 4);
many0!(compatible_brands<&[u8],&str> brand_name);

fn filetype_parser<'a>(input: &'a[u8]) -> IResult<&'a [u8], FileType<'a> > {
  chaining_parser!(input, ||{FileType{major_brand: m, major_brand_version:v, compatible_brands: c}},
    m: brand_name,
    v: major_brand_version,
    c: compatible_brands,)
}

o!(filetype <&[u8], FileType>  ftyp ~ [ filetype_parser ]);

fn filetype_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  //FIXME: flat_map should work here
  //mp4_box(input).flat_map(filetype)
  match mp4_box(input) {
    Done(i, o) => {
      match filetype(o) {
        Done(i2, o2) => {
          Done(i, MP4Box::Ftyp(o2))
        },
        Error(a) => Error(a),
        Incomplete(a) => Incomplete(a)
      }
    },
    Error(a) => Error(a),
    Incomplete(a) => Incomplete(a)
  }
}

tag!(free    "ftyp".as_bytes());
fn free_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match mp4_box(input) {
    Done(i, o) => {
      match free(o) {
        Done(i2, o2) => {
          Done(i, MP4Box::Free)
        },
        Error(a) => Error(a),
        Incomplete(a) => Incomplete(a)
      }
    },
    Error(a) => Error(a),
    Incomplete(a) => Incomplete(a)
  }
}

alt!(box_parser<&[u8], MP4Box>, filetype_box | free_box);

fn data_interpreter(bytes:&[u8]) -> IResult<&[u8], ()> {
  println!("bytes:\n{}", bytes.to_hex(8));
  match box_parser(bytes) {
    Done(i, o) => {
      match o {
        MP4Box::Ftyp(f) => println!("parsed ftyp: {:?}", f),
        MP4Box::Moov    => println!("found moov box"),
        MP4Box::Free    => println!("found free box")
      }
      println!("remaining:\n{}", i.to_hex(8));
      Done(i,())
    },
    Error(a) => {
      println!("error: {:?}", a);
      Error(a)
    },
    Incomplete(a) => {
      println!("incomplete: {:?}", a);
      Incomplete(a)
    }
  }
}
fn parse_mp4_file(filename: &str) {
  FileProducer::new(filename, 150).map(|producer: FileProducer| {
    let mut p = producer;
    /*match p.produce() {
      ProducerState::Data(bytes) => {
      },
      _ => println!("got error")
    }*/
    pusher!(ps, data_interpreter);
    ps(&mut p);
    assert!(false);
  });

}
#[test]
fn file_test() {
  parse_mp4_file("small.mp4");
}
#[test]
fn bunny_test() {
  parse_mp4_file("bigbuckbunny.mp4");
}
<commit_msg>the Free box has the free tag<commit_after>#[macro_use]
extern crate nom;
//extern crate serialize;

use nom::{IResult,FlatMapper,Mapper,Producer,ProducerState,FileProducer};
use nom::IResult::*;

use std::str;
use std::collections::HashMap;
//use serialize::hex::ToHex;

pub trait HexDisplay {
      /// Converts the value of `self` to a hex value, returning the owned
      ///     /// string.
  fn to_hex(&self, chunk_size: usize) -> String;
}

static CHARS: &'static[u8] = b"0123456789abcdef";

impl HexDisplay for [u8] {
    fn to_hex(&self, chunk_size: usize) -> String {
      let mut v = Vec::with_capacity(self.len() * 3);
      let mut i = 0;
      for chunk in self.chunks(chunk_size) {
        let s = format!("{:08x}", i);
        let s2: &str = &s;
        for &ch in s.as_bytes().iter() {
          v.push(ch);
        }
        v.push('\t' as u8);

        i = i + chunk_size;

        for &byte in chunk {
          v.push(CHARS[(byte >> 4) as usize]);
          v.push(CHARS[(byte & 0xf) as usize]);
          v.push(' ' as u8);
        }
        if chunk_size > chunk.len() {
          for i in 0..(chunk_size - chunk.len()) {
            v.push(' ' as u8);
            v.push(' ' as u8);
            v.push(' ' as u8);
          }
        }
        v.push('\t' as u8);

        for &byte in chunk {
          if (byte >=32 && byte <= 126) || byte >= 128 {
            v.push(byte);
          } else {
            v.push('.' as u8);
          }
        }
        v.push('\n' as u8);
      }

      unsafe {
        String::from_utf8_unchecked(v)
      }
    }
}

fn mp4_box(input:&[u8]) -> IResult<&[u8], &[u8]> {

  take!(offset_parser 4);
  match offset_parser(input) {
    Done(i, offset_bytes) => {
      let offset:u32 = (offset_bytes[3] as u32) + (offset_bytes[2] as u32) * 0x100 + (offset_bytes[1] as u32) * 0x10000 + (offset_bytes[0] as u32) * 0x1000000;
      let sz: usize = offset as usize;
      if i.len() >= sz {
        return Done(&i[(sz-4)..], &i[0..(sz-4)])
      } else {
        return Incomplete(0)
      }
    },
    e => e
  }
}

#[derive(PartialEq,Eq,Debug)]
struct FileType<'a> {
  major_brand:         &'a str,
  major_brand_version: &'a [u8],
  compatible_brands:   Vec<&'a str>
}

#[derive(PartialEq,Eq,Debug)]
enum MP4Box<'a> {
  Ftyp(FileType<'a>),
  Moov,
  Free
}

take!(offset 4);
tag!(ftyp    "ftyp".as_bytes());

fn brand_name(input:&[u8]) -> IResult<&[u8],&str> {
  take!(major_brand_bytes 4);
  major_brand_bytes(input).map_res(str::from_utf8)
}
take!(major_brand_version 4);
many0!(compatible_brands<&[u8],&str> brand_name);

fn filetype_parser<'a>(input: &'a[u8]) -> IResult<&'a [u8], FileType<'a> > {
  chaining_parser!(input, ||{FileType{major_brand: m, major_brand_version:v, compatible_brands: c}},
    m: brand_name,
    v: major_brand_version,
    c: compatible_brands,)
}

o!(filetype <&[u8], FileType>  ftyp ~ [ filetype_parser ]);

fn filetype_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  //FIXME: flat_map should work here
  //mp4_box(input).flat_map(filetype)
  match mp4_box(input) {
    Done(i, o) => {
      match filetype(o) {
        Done(i2, o2) => {
          Done(i, MP4Box::Ftyp(o2))
        },
        Error(a) => Error(a),
        Incomplete(a) => Incomplete(a)
      }
    },
    Error(a) => Error(a),
    Incomplete(a) => Incomplete(a)
  }
}

tag!(free    "free".as_bytes());
fn free_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match mp4_box(input) {
    Done(i, o) => {
      match free(o) {
        Done(i2, o2) => {
          Done(i, MP4Box::Free)
        },
        Error(a) => Error(a),
        Incomplete(a) => Incomplete(a)
      }
    },
    Error(a) => Error(a),
    Incomplete(a) => Incomplete(a)
  }
}

alt!(box_parser<&[u8], MP4Box>, filetype_box | free_box);

fn data_interpreter(bytes:&[u8]) -> IResult<&[u8], ()> {
  println!("bytes:\n{}", bytes.to_hex(8));
  match box_parser(bytes) {
    Done(i, o) => {
      match o {
        MP4Box::Ftyp(f) => println!("parsed ftyp: {:?}", f),
        MP4Box::Moov    => println!("found moov box"),
        MP4Box::Free    => println!("found free box")
      }
      println!("remaining:\n{}", i.to_hex(8));
      Done(i,())
    },
    Error(a) => {
      println!("error: {:?}", a);
      Error(a)
    },
    Incomplete(a) => {
      println!("incomplete: {:?}", a);
      Incomplete(a)
    }
  }
}
fn parse_mp4_file(filename: &str) {
  FileProducer::new(filename, 150).map(|producer: FileProducer| {
    let mut p = producer;
    /*match p.produce() {
      ProducerState::Data(bytes) => {
      },
      _ => println!("got error")
    }*/
    pusher!(ps, data_interpreter);
    ps(&mut p);
    assert!(false);
  });

}
#[test]
fn file_test() {
  parse_mp4_file("small.mp4");
}
#[test]
fn bunny_test() {
  parse_mp4_file("bigbuckbunny.mp4");
}
<|endoftext|>