<commit_before>extern crate cobalt;

use std::net;
use std::thread;
use std::time::Duration;
use std::collections::HashMap;
use cobalt::{Client, Connection, ConnectionID, Config, Handler, Server};

#[test]
fn test_client_connection_failure() {

    let config = Config::default();
    let mut handler = MockClientHandler::new();
    let mut client = Client::new(config);
    client.connect(&mut handler, "127.0.0.1:12345").unwrap();

    assert_eq!(handler.connect_calls, 1);
    assert!(handler.tick_connection_calls > 0);
    assert_eq!(handler.close_calls, 1);

    assert_eq!(handler.connection_calls, 0);
    assert_eq!(handler.connection_failed_calls, 1);
    assert_eq!(handler.connection_congestion_state_calls, 0);
    assert_eq!(handler.connection_packet_lost_calls, 0);
    assert_eq!(handler.connection_lost_calls, 0);

}

#[test]
fn test_server_bind_and_shutdown() {

    let config = Config::default();
    let mut handler = MockServerHandler::new(0, false);
    let mut server = Server::new(config);
    server.bind(&mut handler, "127.0.0.1:0").unwrap();

    assert_eq!(handler.bind_calls, 1);
    assert!(handler.tick_connections_calls > 0);
    assert_eq!(handler.shutdown_calls, 1);

    assert_eq!(handler.connection_calls, 0);
    assert_eq!(handler.connection_failed_calls, 0);
    assert_eq!(handler.connection_congestion_state_calls, 0);
    assert_eq!(handler.connection_packet_lost_calls, 0);
    assert_eq!(handler.connection_lost_calls, 0);

}

#[test]
fn test_server_client_connection_lost() {

    // Get a free local socket and then drop it for quick re-use
    // this is not 100% safe but we cannot easily get the locally bound server
    // address after bind() has been called
    let address: Option<net::SocketAddr> = {
        Some(net::UdpSocket::bind("127.0.0.1:0").unwrap().local_addr().unwrap())
    };

    // Setup Test Server
    let server_address = address.clone();
    let server_thread = thread::spawn(move|| {

        let config = Config::default();
        let mut server_handler = MockServerHandler::new(35, false);
        let mut server = Server::new(config);
        server.bind(&mut server_handler, server_address.unwrap()).unwrap();

        assert_eq!(server_handler.bind_calls, 1);
        assert!(server_handler.tick_connections_calls > 0);
        assert_eq!(server_handler.shutdown_calls, 1);

        assert_eq!(server_handler.connection_calls, 1);
        assert_eq!(server_handler.connection_failed_calls, 0);
        assert_eq!(server_handler.connection_congestion_state_calls, 0);
        assert_eq!(server_handler.connection_packet_lost_calls, 0);
        assert_eq!(server_handler.connection_lost_calls, 0);
        assert_eq!(server_handler.connection_closed_calls, 0);

    });

    let config = Config::default();
    let mut client_handler = MockClientHandler::new();
    let mut client = Client::new(config);
    client.connect(&mut client_handler, address.unwrap()).unwrap();

    server_thread.join().unwrap();
    assert_eq!(client_handler.connect_calls, 1);
    assert!(client_handler.tick_connection_calls > 0);
    assert_eq!(client_handler.close_calls, 1);

    assert_eq!(client_handler.connection_calls, 1);
    assert_eq!(client_handler.connection_failed_calls, 0);
    assert_eq!(client_handler.connection_congestion_state_calls, 0);
    // This is somewhat random and depends on how excatly the two threads
    // interact
    // assert_eq!(client_handler.connection_packet_lost_calls, 0);
    assert_eq!(client_handler.connection_lost_calls, 1);
    assert_eq!(client_handler.connection_closed_calls, 0);

}

#[test]
fn test_server_client_connection_close() {

    // Get a free local socket and then drop it for quick re-use
    // this is not 100% safe but we cannot easily get the locally bound server
    // address after bind() has been called
    let address: Option<net::SocketAddr> = {
        Some(net::UdpSocket::bind("127.0.0.1:0").unwrap().local_addr().unwrap())
    };

    // Setup Test Server
    let server_address = address.clone();
    let server_thread = thread::spawn(move|| {

        let config = Config {
            connection_init_threshold: 1000,
            .. Default::default()
        };

        let mut server_handler = MockServerHandler::new(5, true);
        let mut server = Server::new(config);
        server.bind(&mut server_handler, server_address.unwrap()).unwrap();

        assert_eq!(server_handler.connection_lost_calls, 0);
        assert_eq!(server_handler.connection_calls, 1);
        assert_eq!(server_handler.connection_closed_calls, 1);
        assert_eq!(server_handler.closed_by_remote, false);

    });

    let config = Config {
        connection_init_threshold: 1000,
        .. Default::default()
    };

    // TODO cause might be connection marked as dropped by client and
    // an attempted reconnect?
    // client might not receive the closure frame in time?
    //
    // TODO another cause might be that the server thinks the connection is
    // already lost before having send the closure packets? this might explain
    // why the client reconnects afterwards

    let mut client_handler = MockClientHandler::new();
    let mut client = Client::new(config);
    thread::sleep(Duration::from_millis(50));
    client.connect(&mut client_handler, address.unwrap()).unwrap();

    server_thread.join().unwrap();
    assert_eq!(client_handler.connection_lost_calls, 0);
    assert_eq!(client_handler.connection_calls, 1);
    assert_eq!(client_handler.connection_closed_calls, 1);
    assert_eq!(client_handler.closed_by_remote, true);

}

// Client Mock ----------------------------------------------------------------
pub struct MockClientHandler {
    pub connect_calls: u32,
    pub tick_connection_calls: u32,
    pub close_calls: u32,

    pub connection_calls: u32,
    pub connection_failed_calls: u32,
    pub connection_congestion_state_calls: u32,
    pub connection_packet_lost_calls: u32,
    pub connection_lost_calls: u32,
    pub connection_closed_calls: u32,
    pub closed_by_remote: bool
}

impl MockClientHandler {
    pub fn new() -> MockClientHandler {
        MockClientHandler {
            connect_calls: 0,
            tick_connection_calls: 0,
            close_calls: 0,

            connection_calls: 0,
            connection_failed_calls: 0,
            connection_congestion_state_calls: 0,
            connection_packet_lost_calls: 0,
            connection_lost_calls: 0,
            connection_closed_calls: 0,
            closed_by_remote: false
        }
    }
}

impl Handler<Client> for MockClientHandler {

    fn connect(&mut self, _: &mut Client) {
        self.connect_calls += 1;
    }

    fn tick_connection(&mut self, _: &mut Client, _: &mut Connection) {
        self.tick_connection_calls += 1;
    }

    fn close(&mut self, _: &mut Client) {
        self.close_calls += 1;
    }

    fn connection(&mut self, _: &mut Client, _: &mut Connection) {
        self.connection_calls += 1;
    }

    fn connection_failed(&mut self, client: &mut Client, _: &mut Connection) {
        self.connection_failed_calls += 1;
        client.close().unwrap();
    }

    fn connection_packet_lost(
        &mut self, _: &mut Client, _: &mut Connection, _: &[u8]
    ) {
        self.connection_packet_lost_calls += 1;
    }

    fn connection_congestion_state(&mut self, _: &mut Client, _: &mut Connection, _: bool) {
        self.connection_congestion_state_calls += 1;
    }

    fn connection_lost(&mut self, client: &mut Client, _: &mut Connection) {
        self.connection_lost_calls += 1;
        client.close().unwrap();
    }

    fn connection_closed(&mut self, client: &mut Client, _: &mut Connection, by_remote: bool) {
        self.connection_closed_calls += 1;
        self.closed_by_remote = by_remote;
        client.close().unwrap();
    }

}

// Server Mock ----------------------------------------------------------------
pub struct MockServerHandler {

    shutdown_ticks: u32,
    close_connection: bool,

    pub shutdown_calls: u32,
    pub tick_connections_calls: u32,
    pub bind_calls: u32,

    pub connection_calls: u32,
    pub connection_failed_calls: u32,
    pub connection_congestion_state_calls: u32,
    pub connection_packet_lost_calls: u32,
    pub connection_lost_calls: u32,
    pub connection_closed_calls: u32,
    pub closed_by_remote: bool
}

impl MockServerHandler {
    pub fn new(shutdown_ticks: u32, close_connection: bool) -> MockServerHandler {
        MockServerHandler {
            shutdown_ticks: shutdown_ticks,
            close_connection: close_connection,

            shutdown_calls: 0,
            tick_connections_calls: 0,
            bind_calls: 0,

            connection_calls: 0,
            connection_failed_calls: 0,
            connection_congestion_state_calls: 0,
            connection_packet_lost_calls: 0,
            connection_lost_calls: 0,
            connection_closed_calls: 0,
            closed_by_remote: false
        }
    }
}

impl Handler<Server> for MockServerHandler {

    fn bind(&mut self, _: &mut Server) {
        self.bind_calls += 1;
    }

    fn tick_connections(
        &mut self, server: &mut Server,
        connections: &mut HashMap<ConnectionID, Connection>
    ) {

        // Ensure hashmap and connection object have the same id
        for (id, conn) in connections.iter() {
            assert_eq!(*id, conn.id());
        }

        // only advance until initial connection close
        // when there is a connection
        if connections.len() == 0 && self.close_connection {
            self.tick_connections_calls = 0;
        }

        self.tick_connections_calls += 1;

        if self.tick_connections_calls == self.shutdown_ticks {

            // close the client connection the first time around
            if self.close_connection {
                for (_, conn) in connections.iter_mut() {
                    conn.close();
                }

            // shutdown the server
            } else {
                server.shutdown().unwrap();
            }
        }

    }

    fn shutdown(&mut self, _: &mut Server) {
        self.shutdown_calls += 1;
    }

    fn connection(&mut self, _: &mut Server, _: &mut Connection) {
        self.connection_calls += 1;
    }

    fn connection_failed(&mut self, _: &mut Server, _: &mut Connection) {
        self.connection_failed_calls += 1;
    }

    fn connection_packet_lost(
        &mut self, _: &mut Server, _: &mut Connection, _: &[u8]
    ) {
        self.connection_packet_lost_calls += 1;
    }

    fn connection_congestion_state(&mut self, _: &mut Server, _: &mut Connection, _: bool) {
        self.connection_congestion_state_calls += 1;
    }

    fn connection_lost(&mut self, _: &mut Server, _: &mut Connection) {
        self.connection_lost_calls += 1;
    }

    fn connection_closed(&mut self, _: &mut Server, _: &mut Connection, by_remote: bool) {
        self.connection_closed_calls += 1;
        self.closed_by_remote = by_remote;
        self.tick_connections_calls = 0;
        self.shutdown_ticks = 5;
        self.close_connection = false;
    }

}

<commit_msg>[FIX] Fix server shutdown test regression.<commit_after>extern crate cobalt;

use std::net;
use std::thread;
use std::time::Duration;
use std::collections::HashMap;
use cobalt::{Client, Connection, ConnectionID, Config, Handler, Server};

#[test]
fn test_client_connection_failure() {

    let config = Config::default();
    let mut handler = MockClientHandler::new();
    let mut client = Client::new(config);
    client.connect(&mut handler, "127.0.0.1:12345").unwrap();

    assert_eq!(handler.connect_calls, 1);
    assert!(handler.tick_connection_calls > 0);
    assert_eq!(handler.close_calls, 1);

    assert_eq!(handler.connection_calls, 0);
    assert_eq!(handler.connection_failed_calls, 1);
    assert_eq!(handler.connection_congestion_state_calls, 0);
    assert_eq!(handler.connection_packet_lost_calls, 0);
    assert_eq!(handler.connection_lost_calls, 0);

}

#[test]
fn test_server_bind_and_shutdown() {

    let config = Config::default();
    let mut handler = MockServerHandler::new(1, false);
    let mut server = Server::new(config);
    server.bind(&mut handler, "127.0.0.1:0").unwrap();

    assert_eq!(handler.bind_calls, 1);
    assert!(handler.tick_connections_calls > 0);
    assert_eq!(handler.shutdown_calls, 1);

    assert_eq!(handler.connection_calls, 0);
    assert_eq!(handler.connection_failed_calls, 0);
    assert_eq!(handler.connection_congestion_state_calls, 0);
    assert_eq!(handler.connection_packet_lost_calls, 0);
    assert_eq!(handler.connection_lost_calls, 0);

}

#[test]
fn test_server_client_connection_lost() {

    // Get a free local socket and then drop it for quick re-use
    // this is not 100% safe but we cannot easily get the locally bound server
    // address after bind() has been called
    let address: Option<net::SocketAddr> = {
        Some(net::UdpSocket::bind("127.0.0.1:0").unwrap().local_addr().unwrap())
    };

    // Setup Test Server
    let server_address = address.clone();
    let server_thread = thread::spawn(move|| {

        let config = Config::default();
        let mut server_handler = MockServerHandler::new(15, false);
        let mut server = Server::new(config);
        server.bind(&mut server_handler, server_address.unwrap()).unwrap();

        assert_eq!(server_handler.bind_calls, 1);
        assert!(server_handler.tick_connections_calls > 0);
        assert_eq!(server_handler.shutdown_calls, 1);

        assert_eq!(server_handler.connection_calls, 1);
        assert_eq!(server_handler.connection_failed_calls, 0);
        assert_eq!(server_handler.connection_congestion_state_calls, 0);
        assert_eq!(server_handler.connection_packet_lost_calls, 0);
        assert_eq!(server_handler.connection_lost_calls, 0);
        assert_eq!(server_handler.connection_closed_calls, 0);

    });

    let config = Config::default();
    let mut client_handler = MockClientHandler::new();
    let mut client = Client::new(config);
    client.connect(&mut client_handler, address.unwrap()).unwrap();

    server_thread.join().unwrap();
    assert_eq!(client_handler.connect_calls, 1);
    assert!(client_handler.tick_connection_calls > 0);
    assert_eq!(client_handler.close_calls, 1);

    assert_eq!(client_handler.connection_calls, 1);
    assert_eq!(client_handler.connection_failed_calls, 0);
    assert_eq!(client_handler.connection_congestion_state_calls, 0);
    // This is somewhat random and depends on how excatly the two threads
    // interact
    // assert_eq!(client_handler.connection_packet_lost_calls, 0);
    assert_eq!(client_handler.connection_lost_calls, 1);
    assert_eq!(client_handler.connection_closed_calls, 0);

}

#[test]
fn test_server_client_connection_close() {

    // Get a free local socket and then drop it for quick re-use
    // this is not 100% safe but we cannot easily get the locally bound server
    // address after bind() has been called
    let address: Option<net::SocketAddr> = {
        Some(net::UdpSocket::bind("127.0.0.1:0").unwrap().local_addr().unwrap())
    };

    // Setup Test Server
    let server_address = address.clone();
    let server_thread = thread::spawn(move|| {

        let config = Config {
            connection_init_threshold: 1000,
            .. Default::default()
        };

        let mut server_handler = MockServerHandler::new(5, true);
        let mut server = Server::new(config);
        server.bind(&mut server_handler, server_address.unwrap()).unwrap();

        assert_eq!(server_handler.connection_lost_calls, 0);
        assert_eq!(server_handler.connection_calls, 1);
        assert_eq!(server_handler.connection_closed_calls, 1);
        assert_eq!(server_handler.closed_by_remote, false);

    });

    let config = Config {
        connection_init_threshold: 1000,
        .. Default::default()
    };

    // TODO cause might be connection marked as dropped by client and
    // an attempted reconnect?
    // client might not receive the closure frame in time?
    //
    // TODO another cause might be that the server thinks the connection is
    // already lost before having send the closure packets? this might explain
    // why the client reconnects afterwards

    let mut client_handler = MockClientHandler::new();
    let mut client = Client::new(config);
    thread::sleep(Duration::from_millis(50));
    client.connect(&mut client_handler, address.unwrap()).unwrap();

    server_thread.join().unwrap();
    assert_eq!(client_handler.connection_lost_calls, 0);
    assert_eq!(client_handler.connection_calls, 1);
    assert_eq!(client_handler.connection_closed_calls, 1);
    assert_eq!(client_handler.closed_by_remote, true);

}

// Client Mock ----------------------------------------------------------------
pub struct MockClientHandler {
    pub connect_calls: u32,
    pub tick_connection_calls: u32,
    pub close_calls: u32,

    pub connection_calls: u32,
    pub connection_failed_calls: u32,
    pub connection_congestion_state_calls: u32,
    pub connection_packet_lost_calls: u32,
    pub connection_lost_calls: u32,
    pub connection_closed_calls: u32,
    pub closed_by_remote: bool
}

impl MockClientHandler {
    pub fn new() -> MockClientHandler {
        MockClientHandler {
            connect_calls: 0,
            tick_connection_calls: 0,
            close_calls: 0,

            connection_calls: 0,
            connection_failed_calls: 0,
            connection_congestion_state_calls: 0,
            connection_packet_lost_calls: 0,
            connection_lost_calls: 0,
            connection_closed_calls: 0,
            closed_by_remote: false
        }
    }
}

impl Handler<Client> for MockClientHandler {

    fn connect(&mut self, _: &mut Client) {
        self.connect_calls += 1;
    }

    fn tick_connection(&mut self, _: &mut Client, _: &mut Connection) {
        self.tick_connection_calls += 1;
    }

    fn close(&mut self, _: &mut Client) {
        self.close_calls += 1;
    }

    fn connection(&mut self, _: &mut Client, _: &mut Connection) {
        self.connection_calls += 1;
    }

    fn connection_failed(&mut self, client: &mut Client, _: &mut Connection) {
        self.connection_failed_calls += 1;
        client.close().unwrap();
    }

    fn connection_packet_lost(
        &mut self, _: &mut Client, _: &mut Connection, _: &[u8]
    ) {
        self.connection_packet_lost_calls += 1;
    }

    fn connection_congestion_state(&mut self, _: &mut Client, _: &mut Connection, _: bool) {
        self.connection_congestion_state_calls += 1;
    }

    fn connection_lost(&mut self, client: &mut Client, _: &mut Connection) {
        self.connection_lost_calls += 1;
        client.close().unwrap();
    }

    fn connection_closed(&mut self, client: &mut Client, _: &mut Connection, by_remote: bool) {
        self.connection_closed_calls += 1;
        self.closed_by_remote = by_remote;
        client.close().unwrap();
    }

}

// Server Mock ----------------------------------------------------------------
pub struct MockServerHandler {

    shutdown_ticks: u32,
    close_connection: bool,

    pub shutdown_calls: u32,
    pub tick_connections_calls: u32,
    pub bind_calls: u32,

    pub connection_calls: u32,
    pub connection_failed_calls: u32,
    pub connection_congestion_state_calls: u32,
    pub connection_packet_lost_calls: u32,
    pub connection_lost_calls: u32,
    pub connection_closed_calls: u32,
    pub closed_by_remote: bool
}

impl MockServerHandler {
    pub fn new(shutdown_ticks: u32, close_connection: bool) -> MockServerHandler {
        MockServerHandler {
            shutdown_ticks: shutdown_ticks,
            close_connection: close_connection,

            shutdown_calls: 0,
            tick_connections_calls: 0,
            bind_calls: 0,

            connection_calls: 0,
            connection_failed_calls: 0,
            connection_congestion_state_calls: 0,
            connection_packet_lost_calls: 0,
            connection_lost_calls: 0,
            connection_closed_calls: 0,
            closed_by_remote: false
        }
    }
}

impl Handler<Server> for MockServerHandler {

    fn bind(&mut self, _: &mut Server) {
        self.bind_calls += 1;
    }

    fn tick_connections(
        &mut self, server: &mut Server,
        connections: &mut HashMap<ConnectionID, Connection>
    ) {

        // Ensure hashmap and connection object have the same id
        for (id, conn) in connections.iter() {
            assert_eq!(*id, conn.id());
        }

        // only advance until initial connection close
        // when there is a connection
        if connections.len() == 0 && self.close_connection {
            self.tick_connections_calls = 0;
        }

        self.tick_connections_calls += 1;

        if self.tick_connections_calls == self.shutdown_ticks {

            // close the client connection the first time around
            if self.close_connection {
                for (_, conn) in connections.iter_mut() {
                    conn.close();
                }

            // shutdown the server
            } else {
                server.shutdown().unwrap();
            }
        }

    }

    fn shutdown(&mut self, _: &mut Server) {
        self.shutdown_calls += 1;
    }

    fn connection(&mut self, _: &mut Server, _: &mut Connection) {
        self.connection_calls += 1;
    }

    fn connection_failed(&mut self, _: &mut Server, _: &mut Connection) {
        self.connection_failed_calls += 1;
    }

    fn connection_packet_lost(
        &mut self, _: &mut Server, _: &mut Connection, _: &[u8]
    ) {
        self.connection_packet_lost_calls += 1;
    }

    fn connection_congestion_state(&mut self, _: &mut Server, _: &mut Connection, _: bool) {
        self.connection_congestion_state_calls += 1;
    }

    fn connection_lost(&mut self, _: &mut Server, _: &mut Connection) {
        self.connection_lost_calls += 1;
    }

    fn connection_closed(&mut self, _: &mut Server, _: &mut Connection, by_remote: bool) {
        self.connection_closed_calls += 1;
        self.closed_by_remote = by_remote;
        self.tick_connections_calls = 0;
        self.shutdown_ticks = 5;
        self.close_connection = false;
    }

}

<|endoftext|>


<commit_before>extern crate test_server;
extern crate modbus;

#[cfg(feature="modbus-server-tests")]
mod modbus_server_tests {
    use test_server::start_dummy_server;
    use modbus::tcp::{read_coils, read_discrete_inputs, read_input_registers,
                      read_holding_registers, write_single_coil, write_single_register,
                      write_multiple_coils, write_multiple_registers, Ctx};
    use modbus::BitValue;

    /// /////////////////////
    /// simple READ tests
    #[test]
    fn test_read_coils() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert_eq!(read_coils(&mut ctx, 0, 5).unwrap().len(), 5);
        assert!(read_coils(&mut ctx, 0, 5).unwrap().iter().all(|c| *c == BitValue::Off));
    }

    #[test]
    fn test_read_discrete_inputs() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert_eq!(read_discrete_inputs(&mut ctx, 0, 5).unwrap().len(), 5);
        assert!(read_discrete_inputs(&mut ctx, 0, 5).unwrap().iter().all(|c| *c == BitValue::Off));
    }

    #[test]
    fn test_read_holding_registers() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert_eq!(read_holding_registers(&mut ctx, 0, 5).unwrap().len(), 5);
        assert!(read_holding_registers(&mut ctx, 0, 5).unwrap().iter().all(|c| *c == 0));
    }

    #[test]
    fn test_read_input_registers() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert_eq!(read_input_registers(&mut ctx, 0, 5).unwrap().len(), 5);
        assert!(read_input_registers(&mut ctx, 0, 5).unwrap().iter().all(|c| *c == 0));
    }

    /// /////////////////////
    /// simple WRITE tests
    #[test]
    fn test_write_single_coil() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert!(write_single_coil(&mut ctx, 0, BitValue::On).is_ok());
    }

    #[test]
    fn test_write_single_register() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert!(write_single_register(&mut ctx, 0, 1).is_ok());
    }

    #[test]
    fn test_write_multiple_coils() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert!(write_multiple_coils(&mut ctx, 0, &[BitValue::On, BitValue::Off]).is_ok());
        // assert!(write_multiple_coils(&mut ctx, 0, &[]).is_err());
    }

    #[test]
    fn test_write_multiple_registers() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert!(write_multiple_registers(&mut ctx, 0, &[0, 1, 2, 3]).is_ok());
        // assert!(write_multiple_registers(&mut ctx, 0, &[]).is_err());
    }

    /// /////////////////////
    /// coil WRITE-READ tests
    #[test]
    fn test_write_read_single_coils() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();

        assert!(write_single_coil(&mut ctx, 1, BitValue::On).is_ok());
        assert!(write_single_coil(&mut ctx, 3, BitValue::On).is_ok());
        assert_eq!(read_coils(&mut ctx, 0, 5).unwrap(),
                   vec![BitValue::Off, BitValue::On, BitValue::Off, BitValue::On, BitValue::Off]);
        assert_eq!(read_coils(&mut ctx, 1, 5).unwrap(),
                   vec![BitValue::On, BitValue::Off, BitValue::On, BitValue::Off, BitValue::Off]);
        assert!(write_single_coil(&mut ctx, 10, BitValue::On).is_ok());
        assert!(write_single_coil(&mut ctx, 11, BitValue::On).is_ok());
        assert_eq!(read_coils(&mut ctx, 9, 4).unwrap(),
                   vec![BitValue::Off, BitValue::On, BitValue::On, BitValue::Off]);
        assert!(write_single_coil(&mut ctx, 10, BitValue::Off).is_ok());
        assert!(write_single_coil(&mut ctx, 11, BitValue::Off).is_ok());
        assert_eq!(read_coils(&mut ctx, 9, 4).unwrap(),
                   vec![BitValue::Off, BitValue::Off, BitValue::Off, BitValue::Off]);
    }

    #[test]
    fn test_write_read_single_register() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert!(write_single_register(&mut ctx, 0, 23).is_ok());
        assert_eq!(read_holding_registers(&mut ctx, 0, 1).unwrap(), vec![23]);
        assert!(write_single_register(&mut ctx, 0, 0).is_ok());
        assert_eq!(read_holding_registers(&mut ctx, 0, 1).unwrap(), vec![0]);
        assert_eq!(read_input_registers(&mut ctx, 0, 1).unwrap(), vec![0]);
        assert!(write_single_register(&mut ctx, 0, 23).is_ok());
        assert!(write_single_register(&mut ctx, 1, 24).is_ok());
        assert_eq!(read_holding_registers(&mut ctx, 0, 2).unwrap(),
                   vec![23, 24]);
    }

    #[test]
    fn test_write_read_multiple_coils() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert!(write_multiple_coils(&mut ctx, 0, &[BitValue::Off, BitValue::On]).is_ok());
        assert_eq!(read_coils(&mut ctx, 0, 3).unwrap(),
                   &[BitValue::Off, BitValue::On, BitValue::Off]);
        assert!(write_multiple_coils(&mut ctx, 0, &[BitValue::On; 9]).is_ok());
        assert_eq!(read_coils(&mut ctx, 0, 9).unwrap(), &[BitValue::On; 9]);
    }

    #[test]
    fn test_write_read_multiple_registers() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        // assert!(write_multiple_registers(&mut ctx, 0, &[]).is_err());
        assert!(write_multiple_registers(&mut ctx, 0, &[23]).is_ok());
        assert_eq!(read_holding_registers(&mut ctx, 0, 1).unwrap(), &[23]);
        assert!(write_multiple_registers(&mut ctx, 0, &[1, 2, 3]).is_ok());
        assert_eq!(read_holding_registers(&mut ctx, 0, 1).unwrap(), &[1]);
        assert_eq!(read_holding_registers(&mut ctx, 1, 1).unwrap(), &[2]);
        assert_eq!(read_holding_registers(&mut ctx, 2, 1).unwrap(), &[3]);
        assert_eq!(read_holding_registers(&mut ctx, 0, 3).unwrap(), &[1, 2, 3]);
    }
}
<commit_msg>Assert error on writing too much data.<commit_after>extern crate test_server;
extern crate modbus;

#[cfg(feature="modbus-server-tests")]
mod modbus_server_tests {
    use test_server::start_dummy_server;
    use modbus::tcp::{read_coils, read_discrete_inputs, read_input_registers,
                      read_holding_registers, write_single_coil, write_single_register,
                      write_multiple_coils, write_multiple_registers, Ctx};
    use modbus::BitValue;

    /// /////////////////////
    /// simple READ tests
    #[test]
    fn test_read_coils() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert_eq!(read_coils(&mut ctx, 0, 5).unwrap().len(), 5);
        assert!(read_coils(&mut ctx, 0, 5).unwrap().iter().all(|c| *c == BitValue::Off));
    }

    #[test]
    fn test_read_discrete_inputs() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert_eq!(read_discrete_inputs(&mut ctx, 0, 5).unwrap().len(), 5);
        assert!(read_discrete_inputs(&mut ctx, 0, 5).unwrap().iter().all(|c| *c == BitValue::Off));
    }

    #[test]
    fn test_read_holding_registers() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert_eq!(read_holding_registers(&mut ctx, 0, 5).unwrap().len(), 5);
        assert!(read_holding_registers(&mut ctx, 0, 5).unwrap().iter().all(|c| *c == 0));
    }

    #[test]
    fn test_read_input_registers() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert_eq!(read_input_registers(&mut ctx, 0, 5).unwrap().len(), 5);
        assert!(read_input_registers(&mut ctx, 0, 5).unwrap().iter().all(|c| *c == 0));
    }

    /// /////////////////////
    /// simple WRITE tests
    #[test]
    fn test_write_single_coil() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert!(write_single_coil(&mut ctx, 0, BitValue::On).is_ok());
    }

    #[test]
    fn test_write_single_register() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert!(write_single_register(&mut ctx, 0, 1).is_ok());
    }

    #[test]
    fn test_write_multiple_coils() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert!(write_multiple_coils(&mut ctx, 0, &[BitValue::On, BitValue::Off]).is_ok());
        // assert!(write_multiple_coils(&mut ctx, 0, &[]).is_err());
    }

    #[test]
    fn test_write_multiple_registers() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert!(write_multiple_registers(&mut ctx, 0, &[0, 1, 2, 3]).is_ok());
        // assert!(write_multiple_registers(&mut ctx, 0, &[]).is_err());
    }

    /// /////////////////////
    /// coil WRITE-READ tests
    #[test]
    fn test_write_read_single_coils() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();

        assert!(write_single_coil(&mut ctx, 1, BitValue::On).is_ok());
        assert!(write_single_coil(&mut ctx, 3, BitValue::On).is_ok());
        assert_eq!(read_coils(&mut ctx, 0, 5).unwrap(),
                   vec![BitValue::Off, BitValue::On, BitValue::Off, BitValue::On, BitValue::Off]);
        assert_eq!(read_coils(&mut ctx, 1, 5).unwrap(),
                   vec![BitValue::On, BitValue::Off, BitValue::On, BitValue::Off, BitValue::Off]);
        assert!(write_single_coil(&mut ctx, 10, BitValue::On).is_ok());
        assert!(write_single_coil(&mut ctx, 11, BitValue::On).is_ok());
        assert_eq!(read_coils(&mut ctx, 9, 4).unwrap(),
                   vec![BitValue::Off, BitValue::On, BitValue::On, BitValue::Off]);
        assert!(write_single_coil(&mut ctx, 10, BitValue::Off).is_ok());
        assert!(write_single_coil(&mut ctx, 11, BitValue::Off).is_ok());
        assert_eq!(read_coils(&mut ctx, 9, 4).unwrap(),
                   vec![BitValue::Off, BitValue::Off, BitValue::Off, BitValue::Off]);
    }

    #[test]
    fn test_write_read_single_register() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert!(write_single_register(&mut ctx, 0, 23).is_ok());
        assert_eq!(read_holding_registers(&mut ctx, 0, 1).unwrap(), vec![23]);
        assert!(write_single_register(&mut ctx, 0, 0).is_ok());
        assert_eq!(read_holding_registers(&mut ctx, 0, 1).unwrap(), vec![0]);
        assert_eq!(read_input_registers(&mut ctx, 0, 1).unwrap(), vec![0]);
        assert!(write_single_register(&mut ctx, 0, 23).is_ok());
        assert!(write_single_register(&mut ctx, 1, 24).is_ok());
        assert_eq!(read_holding_registers(&mut ctx, 0, 2).unwrap(),
                   vec![23, 24]);
    }

    #[test]
    fn test_write_read_multiple_coils() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        assert!(write_multiple_coils(&mut ctx, 0, &[BitValue::Off, BitValue::On]).is_ok());
        assert_eq!(read_coils(&mut ctx, 0, 3).unwrap(),
                   &[BitValue::Off, BitValue::On, BitValue::Off]);
        assert!(write_multiple_coils(&mut ctx, 0, &[BitValue::On; 9]).is_ok());
        assert_eq!(read_coils(&mut ctx, 0, 9).unwrap(), &[BitValue::On; 9]);
    }

    #[test]
    fn test_write_read_multiple_registers() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        // assert!(write_multiple_registers(&mut ctx, 0, &[]).is_err());
        assert!(write_multiple_registers(&mut ctx, 0, &[23]).is_ok());
        assert_eq!(read_holding_registers(&mut ctx, 0, 1).unwrap(), &[23]);
        assert!(write_multiple_registers(&mut ctx, 0, &[1, 2, 3]).is_ok());
        assert_eq!(read_holding_registers(&mut ctx, 0, 1).unwrap(), &[1]);
        assert_eq!(read_holding_registers(&mut ctx, 1, 1).unwrap(), &[2]);
        assert_eq!(read_holding_registers(&mut ctx, 2, 1).unwrap(), &[3]);
        assert_eq!(read_holding_registers(&mut ctx, 0, 3).unwrap(), &[1, 2, 3]);
    }

    #[test]
    fn test_write_too_big() {
        let (_s, port) = start_dummy_server();
        let mut ctx = Ctx::new_with_port("127.0.0.1", port).unwrap();
        // (MODBUS_MAX_WRITE_COUNT - HEADER) / u16-bytes
        assert!(write_multiple_registers(&mut ctx, 0, &[0xdead; (0x79 - 12) / 2]).is_ok());
        assert!(write_multiple_registers(&mut ctx, 0, &[0xdead; (0x79 - 11) / 2]).is_err());
    }
}
<|endoftext|>


<commit_before>extern crate find_folder;

use screen::*;
use piston_window;
use conrod;
use conrod::Widget;
use conrod::Frameable;
use conrod::color::Colorable;
use conrod::Positionable;

pub struct MainMenuScreen;

impl MainMenuScreen {
    pub fn new() -> MainMenuScreen {
        MainMenuScreen
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self, input: &piston_window::Input, window: &piston_window::PistonWindow) -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        window.draw_2d(|context, graphics| {
            piston_window::clear([0., 0., 1., 1.0], graphics);

////////////////////////////////////////////////////////////////////////////////////
        // TODO: Move Ui to some context?
        // piston_window::Glyphs
        // type Ui = conrod::Ui<Glyphs>;
        let mut ui = {
            let assets = find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap();
            let font_path = assets.join("NotoSans-Regular.ttf");
            let theme = conrod::Theme::default();
            let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
            conrod::Ui::new(glyph_cache.unwrap(), theme)
        };

        conrod::Canvas::new()
            .frame(200.)
            .pad(30.0)
            .color(conrod::color::rgb(0.2, 0.35, 0.45))
            .scroll_kids()
            .set(CANVAS, &mut ui);

        conrod::Text::new("Widget Demonstration")
            .top_left_with_margins_on(CANVAS, 0.0, 350.0)
            .font_size(32)
            .color(conrod::color::rgb(0.2, 0.35, 0.45).plain_contrast())
            .set(TITLE, &mut ui);
////////////////////////////////////////////////////////////////////////////////////
        });
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {}
}

widget_ids! {
    CANVAS,
    TITLE,
}
<commit_msg>Working conrod<commit_after>extern crate find_folder;

use screen::*;
use piston_window;
use conrod;
use conrod::Widget;
use conrod::Frameable;
use conrod::color::Colorable;
use conrod::Positionable;

pub struct MainMenuScreen;

impl MainMenuScreen {
    pub fn new() -> MainMenuScreen {
        MainMenuScreen
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self, input: &piston_window::Input, window: &piston_window::PistonWindow) -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        // TODO: Move Ui to some context?
        // piston_window::Glyphs
        // type Ui = conrod::Ui<Glyphs>;
        let mut ui = {
            let assets = find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap();
            let font_path = assets.join("NotoSans-Regular.ttf");
            let theme = conrod::Theme::default();
            let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
            conrod::Ui::new(glyph_cache.unwrap(), theme)
        };

        ui.handle_event(window);

        //window.update(|_| {
        ui.set_widgets(|ui| {
            conrod::Canvas::new()
                .frame(200.)
                .pad(30.0)
                .color(conrod::color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            conrod::Text::new("Widget Demonstration")
                .top_left_with_margins_on(CANVAS, 0.0, 350.0)
                .font_size(32)
                .color(conrod::color::rgb(0.2, 0.35, 0.45).plain_contrast())
                .set(TITLE, ui);
        });

        window.draw_2d(|context, graphics| ui.draw(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {}
}

widget_ids! {
    CANVAS,
    TITLE,
}
<|endoftext|>


<commit_before>//! An `Operation` captures the semantics of the IL.

use std::fmt;
use il::*;

/// An IL Operation updates some state.
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum Operation {
    /// Assign the value given in expression to the variable indicated.
    Assign {
        dst: Scalar,
        src: Expression
    },
    /// Store the value in src at the address given in index.
    Store {
        index: Expression,
        src: Expression
    },
    /// Load the value in memory at index and place the result in the variable dst.
    Load {
        dst: Scalar,
        index: Expression,
    },
    /// Branch to the value given by target.
    Branch {
        target: Expression
    },
    /// Holds an Intrinsic for unmodellable instructions
    Intrinsic {
        intrinsic: Intrinsic
    },
    /// An operation that does nothing, and allows for a placeholder
    /// `Instuction`
    Nop
}

impl Operation {
    /// Create a new `Operation::Assign`.
    pub fn assign(dst: Scalar, src: Expression) -> Operation {
        Operation::Assign {
            dst: dst,
            src: src
        }
    }

    /// Create a new `Operation::Store`.
    pub fn store(index: Expression, src: Expression) -> Operation {
        Operation::Store { index: index, src: src }
    }

    /// Create a new `Operation::Load`.
    pub fn load(dst: Scalar, index: Expression) -> Operation {
        Operation::Load { dst: dst, index: index }
    }

    /// Create a new `Operation::Brc`.
    pub fn branch(target: Expression) -> Operation {
        Operation::Branch { target: target }
    }

    /// Create a new `Operation::Intrinsic`.
    pub fn intrinsic(intrinsic: Intrinsic) -> Operation {
        Operation::Intrinsic { intrinsic: intrinsic }
    }

    /// Create a new `Operation::Nop`
    pub fn nop() -> Operation {
        Operation::Nop
    }

    /// Get each `Scalar` read by this `Operation`.
    pub fn scalars_read(&self) -> Option<Vec<&Scalar>> {
        match *self {
            Operation::Assign { ref src, .. } => Some(src.scalars()),
            Operation::Store { ref index, ref src } =>
                Some(index.scalars()
                          .into_iter()
                          .chain(src.scalars().into_iter())
                          .collect()),
            Operation::Load { ref index, .. } => Some(index.scalars()),
            Operation::Branch { ref target } => Some(target.scalars()),
            Operation::Intrinsic { ref intrinsic } => intrinsic.scalars_read(),
            Operation::Nop => Some(Vec::new())
        }
    }

    /// Get a mutable reference to each `Scalar` read by this `Operation`.
    pub fn scalars_read_mut(&mut self) -> Option<Vec<&mut Scalar>> {
        match *self {
            Operation::Assign { ref mut src, .. } => Some(src.scalars_mut()),
            Operation::Store { ref mut index, ref mut src } =>
                Some(index.scalars_mut()
                          .into_iter()
                          .chain(src.scalars_mut().into_iter())
                          .collect()),
            Operation::Load { ref mut index, .. } => Some(index.scalars_mut()),
            Operation::Branch { ref mut target } => Some(target.scalars_mut()),
            Operation::Intrinsic { ref mut intrinsic } =>
                intrinsic.scalars_read_mut(),
            Operation::Nop => Some(Vec::new())
        }
    }

    /// Get a Vec of the `Scalar`s written by this `Operation`
    pub fn scalars_written(&self) -> Option<Vec<&Scalar>> {
        match *self {
            Operation::Assign { ref dst, .. } |
            Operation::Load   { ref dst, .. } => Some(vec![dst]),
            Operation::Store  { .. } |
            Operation::Branch { .. } => Some(Vec::new()),
            Operation::Intrinsic { ref intrinsic } =>
                intrinsic.scalars_written(),
            Operation::Nop => Some(Vec::new())
        }
    }

    /// Get a Vec of mutable referencer to the `Scalar`s written by this
    /// `Operation`
    pub fn scalars_written_mut(&mut self) -> Option<Vec<&mut Scalar>> {
        match *self {
            Operation::Assign { ref mut dst, .. } |
            Operation::Load   { ref mut dst, .. } => Some(vec![dst]),
            Operation::Store  { .. } |
            Operation::Branch { .. } => Some(Vec::new()),
            Operation::Intrinsic { ref mut intrinsic } =>
                intrinsic.scalars_written_mut(),
            Operation::Nop => Some(Vec::new())
        }
    }
}

impl fmt::Display for Operation {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Operation::Assign { ref dst, ref src } =>
                write!(f, "{} = {}", dst, src),
            Operation::Store { ref index, ref src } =>
                write!(f, "[{}] = {}", index, src),
            Operation::Load { ref dst, ref index } =>
                write!(f, "{} = [{}]", dst, index),
            Operation::Branch { ref target } =>
                write!(f, "branch {}", target),
            Operation::Intrinsic { ref intrinsic } =>
                write!(f, "intrinsic {}", intrinsic),
            Operation::Nop => write!(f, "nop")
        }
    }
}<commit_msg>functions over il::Operation to check for operation type<commit_after>//! An `Operation` captures the semantics of the IL.

use std::fmt;
use il::*;

/// An IL Operation updates some state.
#[derive(Clone, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub enum Operation {
    /// Assign the value given in expression to the variable indicated.
    Assign {
        dst: Scalar,
        src: Expression
    },
    /// Store the value in src at the address given in index.
    Store {
        index: Expression,
        src: Expression
    },
    /// Load the value in memory at index and place the result in the variable dst.
    Load {
        dst: Scalar,
        index: Expression,
    },
    /// Branch to the value given by target.
    Branch {
        target: Expression
    },
    /// Holds an Intrinsic for unmodellable instructions
    Intrinsic {
        intrinsic: Intrinsic
    },
    /// An operation that does nothing, and allows for a placeholder
    /// `Instuction`
    Nop
}

impl Operation {
    /// Create a new `Operation::Assign`.
    pub fn assign(dst: Scalar, src: Expression) -> Operation {
        Operation::Assign {
            dst: dst,
            src: src
        }
    }

    /// Create a new `Operation::Store`.
    pub fn store(index: Expression, src: Expression) -> Operation {
        Operation::Store { index: index, src: src }
    }

    /// Create a new `Operation::Load`.
    pub fn load(dst: Scalar, index: Expression) -> Operation {
        Operation::Load { dst: dst, index: index }
    }

    /// Create a new `Operation::Brc`.
    pub fn branch(target: Expression) -> Operation {
        Operation::Branch { target: target }
    }

    /// Create a new `Operation::Intrinsic`.
    pub fn intrinsic(intrinsic: Intrinsic) -> Operation {
        Operation::Intrinsic { intrinsic: intrinsic }
    }

    /// Create a new `Operation::Nop`
    pub fn nop() -> Operation {
        Operation::Nop
    }

    pub fn is_assign(&self) -> bool {
        match self { Operation::Assign { .. } => true, _ => false }
    }

    pub fn is_store(&self) -> bool {
        match self { Operation::Store { .. } => true, _ => false }
    }

    pub fn is_load(&self) -> bool {
        match self { Operation::Load { .. } => true, _ => false }
    }

    pub fn is_branch(&self) -> bool {
        match self { Operation::Branch { .. } => true, _ => false }
    }

    pub fn is_intrinsic(&self) -> bool {
        match self { Operation::Intrinsic { .. } => true, _ => false }
    }

    pub fn is_nop(&self) -> bool {
        match self { Operation::Nop => true, _ => false }
    }

    /// Get each `Scalar` read by this `Operation`.
    pub fn scalars_read(&self) -> Option<Vec<&Scalar>> {
        match *self {
            Operation::Assign { ref src, .. } => Some(src.scalars()),
            Operation::Store { ref index, ref src } =>
                Some(index.scalars()
                          .into_iter()
                          .chain(src.scalars().into_iter())
                          .collect()),
            Operation::Load { ref index, .. } => Some(index.scalars()),
            Operation::Branch { ref target } => Some(target.scalars()),
            Operation::Intrinsic { ref intrinsic } => intrinsic.scalars_read(),
            Operation::Nop => Some(Vec::new())
        }
    }

    /// Get a mutable reference to each `Scalar` read by this `Operation`.
    pub fn scalars_read_mut(&mut self) -> Option<Vec<&mut Scalar>> {
        match *self {
            Operation::Assign { ref mut src, .. } => Some(src.scalars_mut()),
            Operation::Store { ref mut index, ref mut src } =>
                Some(index.scalars_mut()
                          .into_iter()
                          .chain(src.scalars_mut().into_iter())
                          .collect()),
            Operation::Load { ref mut index, .. } => Some(index.scalars_mut()),
            Operation::Branch { ref mut target } => Some(target.scalars_mut()),
            Operation::Intrinsic { ref mut intrinsic } =>
                intrinsic.scalars_read_mut(),
            Operation::Nop => Some(Vec::new())
        }
    }

    /// Get a Vec of the `Scalar`s written by this `Operation`
    pub fn scalars_written(&self) -> Option<Vec<&Scalar>> {
        match *self {
            Operation::Assign { ref dst, .. } |
            Operation::Load   { ref dst, .. } => Some(vec![dst]),
            Operation::Store  { .. } |
            Operation::Branch { .. } => Some(Vec::new()),
            Operation::Intrinsic { ref intrinsic } =>
                intrinsic.scalars_written(),
            Operation::Nop => Some(Vec::new())
        }
    }

    /// Get a Vec of mutable referencer to the `Scalar`s written by this
    /// `Operation`
    pub fn scalars_written_mut(&mut self) -> Option<Vec<&mut Scalar>> {
        match *self {
            Operation::Assign { ref mut dst, .. } |
            Operation::Load   { ref mut dst, .. } => Some(vec![dst]),
            Operation::Store  { .. } |
            Operation::Branch { .. } => Some(Vec::new()),
            Operation::Intrinsic { ref mut intrinsic } =>
                intrinsic.scalars_written_mut(),
            Operation::Nop => Some(Vec::new())
        }
    }
}

impl fmt::Display for Operation {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Operation::Assign { ref dst, ref src } =>
                write!(f, "{} = {}", dst, src),
            Operation::Store { ref index, ref src } =>
                write!(f, "[{}] = {}", index, src),
            Operation::Load { ref dst, ref index } =>
                write!(f, "{} = [{}]", dst, index),
            Operation::Branch { ref target } =>
                write!(f, "branch {}", target),
            Operation::Intrinsic { ref intrinsic } =>
                write!(f, "intrinsic {}", intrinsic),
            Operation::Nop => write!(f, "nop")
        }
    }
}<|endoftext|>


<commit_before>use config::Config;
use error::BackendError;

pub mod anilist;

pub trait SyncBackend
where
    Self: Sized,
{
    fn init(config: &mut Config) -> Result<Self, BackendError>;
    fn find_series_by_name(&self, name: &str) -> Result<Vec<AnimeInfo>, BackendError>;
}

pub struct AnimeInfo {
    pub id: u32,
}
<commit_msg>Add episodes and title fields to AnimeInfo struct Add Debug and Deserialize traits to AnimeInfo struct<commit_after>use config::Config;
use error::BackendError;

pub mod anilist;

pub trait SyncBackend
where
    Self: Sized,
{
    fn init(config: &mut Config) -> Result<Self, BackendError>;
    fn find_series_by_name(&self, name: &str) -> Result<Vec<AnimeInfo>, BackendError>;
}

#[derive(Debug, Deserialize)]
pub struct AnimeInfo {
    pub id: u32,
    pub title: String,
    pub episodes: u32,
}
<|endoftext|>


<commit_before>use std::path::{Path, PathBuf};
use std::fs::{self, File};
use std::io::Write;
use std::error::Error;

use {BookConfig, BookItem, theme, parse, utils};
use book::BookItems;
use renderer::{Renderer, HtmlHandlebars};
use utils::{PathExt, create_path};

pub struct MDBook {
    config: BookConfig,
    pub content: Vec<BookItem>,
    renderer: Box<Renderer>,
}

impl MDBook {

    /// Create a new `MDBook` struct with root directory `root`
    ///
    /// - The default source directory is set to `root/src`
    /// - The default output directory is set to `root/book`
    ///
    /// They can both be changed by using [`set_src()`](#method.set_src) and [`set_dest()`](#method.set_dest)

    pub fn new(root: &Path) -> MDBook {

        if !root.exists() || !root.is_dir() {
            output!("{:?} No directory with that name", root);
        }

        MDBook {
            content: vec![],
            config: BookConfig::new(root)
                        .set_src(&root.join("src"))
                        .set_dest(&root.join("book"))
                        .to_owned(),
            renderer: Box::new(HtmlHandlebars::new()),
        }
    }

    /// Returns a flat depth-first iterator over the elements of the book, it returns an [BookItem enum](bookitem.html):
    /// `(section: String, bookitem: &BookItem)`
    ///
    /// ```no_run
    /// # extern crate mdbook;
    /// # use mdbook::MDBook;
    /// # use bookitem::BookItem;
    /// # use std::path::Path;
    /// # fn main() {
    /// # let mut book = MDBook::new(Path::new("mybook"));
    /// for item in book.iter() {
    ///     match item {
    ///         BookItem::Chapter(section, chapter) => {},
    ///         BookItem::Affix(chapter) => {},
    ///         BookItem::Spacer => {},
    ///     }
    /// }
    ///
    /// // would print something like this:
    /// // 1. Chapter 1
    /// // 1.1 Sub Chapter
    /// // 1.2 Sub Chapter
    /// // 2. Chapter 2
    /// //
    /// // etc.
    /// # }
    /// ```

    pub fn iter(&self) -> BookItems {
        BookItems {
            items: &self.content[..],
            current_index: 0,
            stack: Vec::new(),
        }
    }

    /// `init()` creates some boilerplate files and directories to get you started with your book.
    ///
    /// ```text
    /// book-test/
    /// ├── book
    /// └── src
    ///     ├── chapter_1.md
    ///     └── SUMMARY.md
    /// ```
    ///
    /// It uses the paths given as source and output directories and adds a `SUMMARY.md` and a
    /// `chapter_1.md` to the source directory.

    pub fn init(&mut self) -> Result<(), Box<Error>> {

        debug!("[fn]: init");

        if !self.config.get_root().exists() {
            create_path(self.config.get_root()).unwrap();
            output!("{:?} created", self.config.get_root());
        }

        {
            let dest = self.config.get_dest();
            let src = self.config.get_src();

            if !dest.exists() {
                debug!("[*]: {:?} does not exist, trying to create directory", dest);
                try!(fs::create_dir(&dest));
            }

            if !src.exists() {
                debug!("[*]: {:?} does not exist, trying to create directory", src);
                try!(fs::create_dir(&src));
            }

            let summary = src.join("SUMMARY.md");

            if !summary.exists() {

                // Summary does not exist, create it

                debug!("[*]: {:?} does not exist, trying to create SUMMARY.md", src.join("SUMMARY.md"));
                let mut f = try!(File::create(&src.join("SUMMARY.md")));

                debug!("[*]: Writing to SUMMARY.md");

                try!(writeln!(f, "# Summary"));
                try!(writeln!(f, ""));
                try!(writeln!(f, "- [Chapter 1](./chapter_1.md)"));
            }
        }

        // parse SUMMARY.md, and create the missing item related file
        try!(self.parse_summary());

        debug!("[*]: constructing paths for missing files");
        for item in self.iter() {
            debug!("[*]: item: {:?}", item);
            match item {
                &BookItem::Spacer => continue,
                &BookItem::Chapter(_, ref ch) | &BookItem::Affix(ref ch) => {
                    if ch.path != PathBuf::new() {
                        let path = self.config.get_src().join(&ch.path);

                        if !path.exists() {
                            debug!("[*]: {:?} does not exist, trying to create file", path);
                            try!(::std::fs::create_dir_all(path.parent().unwrap()));
                            let mut f = try!(File::create(path));

                            //debug!("[*]: Writing to {:?}", path);
                            try!(writeln!(f, "# {}", ch.name));
                        }
                    }
                }
            }
        }

        debug!("[*]: init done");
        return Ok(());
    }

    /// The `build()` method is the one where everything happens. First it parses `SUMMARY.md` to
    /// construct the book's structure in the form of a `Vec<BookItem>` and then calls `render()`
    /// method of the current renderer.
    ///
    /// It is the renderer who generates all the output files.

    pub fn build(&mut self) -> Result<(), Box<Error>> {
        debug!("[fn]: build");

        try!(self.init());

        // Clean output directory
        try!(utils::remove_dir_content(&self.config.get_dest()));

        try!(self.renderer.render(&self));

        Ok(())
    }

    pub fn copy_theme(&self) -> Result<(), Box<Error>> {
        debug!("[fn]: copy_theme");

        let theme_dir = self.config.get_src().join("theme");

        if !theme_dir.exists() {
            debug!("[*]: {:?} does not exist, trying to create directory", theme_dir);
            try!(fs::create_dir(&theme_dir));
        }

        // index.hbs
        let mut index = try!(File::create(&theme_dir.join("index.hbs")));
        try!(index.write_all(theme::INDEX));

        // book.css
        let mut css = try!(File::create(&theme_dir.join("book.css")));
        try!(css.write_all(theme::CSS));

        // book.js
        let mut js = try!(File::create(&theme_dir.join("book.js")));
        try!(js.write_all(theme::JS));

        // highlight.css
        let mut highlight_css = try!(File::create(&theme_dir.join("highlight.css")));
        try!(highlight_css.write_all(theme::HIGHLIGHT_CSS));

        // highlight.js
        let mut highlight_js = try!(File::create(&theme_dir.join("highlight.js")));
        try!(highlight_js.write_all(theme::HIGHLIGHT_JS));

        Ok(())
    }

    /// Parses the `book.json` file (if it exists) to extract the configuration parameters.
    /// The `book.json` file should be in the root directory of the book.
    /// The root directory is the one specified when creating a new `MDBook`
    ///
    /// ```no_run
    /// # extern crate mdbook;
    /// # use mdbook::MDBook;
    /// # use std::path::Path;
    /// # fn main() {
    /// let mut book = MDBook::new(Path::new("root_dir"));
    /// # }
    /// ```
    ///
    /// In this example, `root_dir` will be the root directory of our book and is specified in function
    /// of the current working directory by using a relative path instead of an absolute path.

    pub fn read_config(mut self) -> Self {
        let root = self.config.get_root().to_owned();
        self.config.read_config(&root);
        self
    }

    /// You can change the default renderer to another one by using this method. The only requirement
    /// is for your renderer to implement the [Renderer trait](../../renderer/renderer/trait.Renderer.html)
    ///
    /// ```no_run
    /// extern crate mdbook;
    /// use mdbook::MDBook;
    /// use mdbook::renderer::HtmlHandlebars;
    /// # use std::path::Path;
    ///
    /// fn main() {
    ///     let mut book = MDBook::new(Path::new("mybook"))
    ///                         .set_renderer(Box::new(HtmlHandlebars::new()));
    ///
    ///     // In this example we replace the default renderer by the default renderer...
    ///     // Don't forget to put your renderer in a Box
    /// }
    /// ```
    ///
    /// **note:** Don't forget to put your renderer in a `Box` before passing it to `set_renderer()`

    pub fn set_renderer(mut self, renderer: Box<Renderer>) -> Self {
        self.renderer = renderer;
        self
    }

    pub fn set_dest(mut self, dest: &Path) -> Self {

        // Handle absolute and relative paths
        match dest.is_absolute() {
            true => { self.config.set_dest(dest); },
            false => {
                let dest = self.config.get_root().join(dest).to_owned();
                self.config.set_dest(&dest);
            }
        }

        self
    }

    pub fn get_dest(&self) -> &Path {
        self.config.get_dest()
    }

    pub fn set_src(mut self, src: &Path) -> Self {

        // Handle absolute and relative paths
        match src.is_absolute() {
            true => { self.config.set_src(src); },
            false => {
                let src = self.config.get_root().join(src).to_owned();
                self.config.set_src(&src);
            }
        }

        self
    }

    pub fn get_src(&self) -> &Path {
        self.config.get_src()
    }

    pub fn set_title(mut self, title: &str) -> Self {
        self.config.title = title.to_owned();
        self
    }

    pub fn get_title(&self) -> &str {
        &self.config.title
    }

    pub fn set_author(mut self, author: &str) -> Self {
        self.config.author = author.to_owned();
        self
    }

    pub fn get_author(&self) -> &str {
        &self.config.author
    }

    // Construct book
    fn parse_summary(&mut self) -> Result<(), Box<Error>> {
        // When append becomes stable, use self.content.append() ...
        self.content = try!(parse::construct_bookitems(&self.config.get_src().join("SUMMARY.md")));
        Ok(())
    }

}
<commit_msg>Fix doc test II<commit_after>use std::path::{Path, PathBuf};
use std::fs::{self, File};
use std::io::Write;
use std::error::Error;

use {BookConfig, BookItem, theme, parse, utils};
use book::BookItems;
use renderer::{Renderer, HtmlHandlebars};
use utils::{PathExt, create_path};

pub struct MDBook {
    config: BookConfig,
    pub content: Vec<BookItem>,
    renderer: Box<Renderer>,
}

impl MDBook {

    /// Create a new `MDBook` struct with root directory `root`
    ///
    /// - The default source directory is set to `root/src`
    /// - The default output directory is set to `root/book`
    ///
    /// They can both be changed by using [`set_src()`](#method.set_src) and [`set_dest()`](#method.set_dest)

    pub fn new(root: &Path) -> MDBook {

        if !root.exists() || !root.is_dir() {
            output!("{:?} No directory with that name", root);
        }

        MDBook {
            content: vec![],
            config: BookConfig::new(root)
                        .set_src(&root.join("src"))
                        .set_dest(&root.join("book"))
                        .to_owned(),
            renderer: Box::new(HtmlHandlebars::new()),
        }
    }

    /// Returns a flat depth-first iterator over the elements of the book, it returns an [BookItem enum](bookitem.html):
    /// `(section: String, bookitem: &BookItem)`
    ///
    /// ```no_run
    /// # extern crate mdbook;
    /// # use mdbook::MDBook;
    /// # use mdbook::BookItem;
    /// # use std::path::Path;
    /// # fn main() {
    /// # let mut book = MDBook::new(Path::new("mybook"));
    /// for item in book.iter() {
    ///     match item {
    ///         &BookItem::Chapter(ref section, ref chapter) => {},
    ///         &BookItem::Affix(ref chapter) => {},
    ///         &BookItem::Spacer => {},
    ///     }
    /// }
    ///
    /// // would print something like this:
    /// // 1. Chapter 1
    /// // 1.1 Sub Chapter
    /// // 1.2 Sub Chapter
    /// // 2. Chapter 2
    /// //
    /// // etc.
    /// # }
    /// ```

    pub fn iter(&self) -> BookItems {
        BookItems {
            items: &self.content[..],
            current_index: 0,
            stack: Vec::new(),
        }
    }

    /// `init()` creates some boilerplate files and directories to get you started with your book.
    ///
    /// ```text
    /// book-test/
    /// ├── book
    /// └── src
    ///     ├── chapter_1.md
    ///     └── SUMMARY.md
    /// ```
    ///
    /// It uses the paths given as source and output directories and adds a `SUMMARY.md` and a
    /// `chapter_1.md` to the source directory.

    pub fn init(&mut self) -> Result<(), Box<Error>> {

        debug!("[fn]: init");

        if !self.config.get_root().exists() {
            create_path(self.config.get_root()).unwrap();
            output!("{:?} created", self.config.get_root());
        }

        {
            let dest = self.config.get_dest();
            let src = self.config.get_src();

            if !dest.exists() {
                debug!("[*]: {:?} does not exist, trying to create directory", dest);
                try!(fs::create_dir(&dest));
            }

            if !src.exists() {
                debug!("[*]: {:?} does not exist, trying to create directory", src);
                try!(fs::create_dir(&src));
            }

            let summary = src.join("SUMMARY.md");

            if !summary.exists() {

                // Summary does not exist, create it

                debug!("[*]: {:?} does not exist, trying to create SUMMARY.md", src.join("SUMMARY.md"));
                let mut f = try!(File::create(&src.join("SUMMARY.md")));

                debug!("[*]: Writing to SUMMARY.md");

                try!(writeln!(f, "# Summary"));
                try!(writeln!(f, ""));
                try!(writeln!(f, "- [Chapter 1](./chapter_1.md)"));
            }
        }

        // parse SUMMARY.md, and create the missing item related file
        try!(self.parse_summary());

        debug!("[*]: constructing paths for missing files");
        for item in self.iter() {
            debug!("[*]: item: {:?}", item);
            match item {
                &BookItem::Spacer => continue,
                &BookItem::Chapter(_, ref ch) | &BookItem::Affix(ref ch) => {
                    if ch.path != PathBuf::new() {
                        let path = self.config.get_src().join(&ch.path);

                        if !path.exists() {
                            debug!("[*]: {:?} does not exist, trying to create file", path);
                            try!(::std::fs::create_dir_all(path.parent().unwrap()));
                            let mut f = try!(File::create(path));

                            //debug!("[*]: Writing to {:?}", path);
                            try!(writeln!(f, "# {}", ch.name));
                        }
                    }
                }
            }
        }

        debug!("[*]: init done");
        return Ok(());
    }

    /// The `build()` method is the one where everything happens. First it parses `SUMMARY.md` to
    /// construct the book's structure in the form of a `Vec<BookItem>` and then calls `render()`
    /// method of the current renderer.
    ///
    /// It is the renderer who generates all the output files.

    pub fn build(&mut self) -> Result<(), Box<Error>> {
        debug!("[fn]: build");

        try!(self.init());

        // Clean output directory
        try!(utils::remove_dir_content(&self.config.get_dest()));

        try!(self.renderer.render(&self));

        Ok(())
    }

    pub fn copy_theme(&self) -> Result<(), Box<Error>> {
        debug!("[fn]: copy_theme");

        let theme_dir = self.config.get_src().join("theme");

        if !theme_dir.exists() {
            debug!("[*]: {:?} does not exist, trying to create directory", theme_dir);
            try!(fs::create_dir(&theme_dir));
        }

        // index.hbs
        let mut index = try!(File::create(&theme_dir.join("index.hbs")));
        try!(index.write_all(theme::INDEX));

        // book.css
        let mut css = try!(File::create(&theme_dir.join("book.css")));
        try!(css.write_all(theme::CSS));

        // book.js
        let mut js = try!(File::create(&theme_dir.join("book.js")));
        try!(js.write_all(theme::JS));

        // highlight.css
        let mut highlight_css = try!(File::create(&theme_dir.join("highlight.css")));
        try!(highlight_css.write_all(theme::HIGHLIGHT_CSS));

        // highlight.js
        let mut highlight_js = try!(File::create(&theme_dir.join("highlight.js")));
        try!(highlight_js.write_all(theme::HIGHLIGHT_JS));

        Ok(())
    }

    /// Parses the `book.json` file (if it exists) to extract the configuration parameters.
    /// The `book.json` file should be in the root directory of the book.
    /// The root directory is the one specified when creating a new `MDBook`
    ///
    /// ```no_run
    /// # extern crate mdbook;
    /// # use mdbook::MDBook;
    /// # use std::path::Path;
    /// # fn main() {
    /// let mut book = MDBook::new(Path::new("root_dir"));
    /// # }
    /// ```
    ///
    /// In this example, `root_dir` will be the root directory of our book and is specified in function
    /// of the current working directory by using a relative path instead of an absolute path.

    pub fn read_config(mut self) -> Self {
        let root = self.config.get_root().to_owned();
        self.config.read_config(&root);
        self
    }

    /// You can change the default renderer to another one by using this method. The only requirement
    /// is for your renderer to implement the [Renderer trait](../../renderer/renderer/trait.Renderer.html)
    ///
    /// ```no_run
    /// extern crate mdbook;
    /// use mdbook::MDBook;
    /// use mdbook::renderer::HtmlHandlebars;
    /// # use std::path::Path;
    ///
    /// fn main() {
    ///     let mut book = MDBook::new(Path::new("mybook"))
    ///                         .set_renderer(Box::new(HtmlHandlebars::new()));
    ///
    ///     // In this example we replace the default renderer by the default renderer...
    ///     // Don't forget to put your renderer in a Box
    /// }
    /// ```
    ///
    /// **note:** Don't forget to put your renderer in a `Box` before passing it to `set_renderer()`

    pub fn set_renderer(mut self, renderer: Box<Renderer>) -> Self {
        self.renderer = renderer;
        self
    }

    pub fn set_dest(mut self, dest: &Path) -> Self {

        // Handle absolute and relative paths
        match dest.is_absolute() {
            true => { self.config.set_dest(dest); },
            false => {
                let dest = self.config.get_root().join(dest).to_owned();
                self.config.set_dest(&dest);
            }
        }

        self
    }

    pub fn get_dest(&self) -> &Path {
        self.config.get_dest()
    }

    pub fn set_src(mut self, src: &Path) -> Self {

        // Handle absolute and relative paths
        match src.is_absolute() {
            true => { self.config.set_src(src); },
            false => {
                let src = self.config.get_root().join(src).to_owned();
                self.config.set_src(&src);
            }
        }

        self
    }

    pub fn get_src(&self) -> &Path {
        self.config.get_src()
    }

    pub fn set_title(mut self, title: &str) -> Self {
        self.config.title = title.to_owned();
        self
    }

    pub fn get_title(&self) -> &str {
        &self.config.title
    }

    pub fn set_author(mut self, author: &str) -> Self {
        self.config.author = author.to_owned();
        self
    }

    pub fn get_author(&self) -> &str {
        &self.config.author
    }

    // Construct book
    fn parse_summary(&mut self) -> Result<(), Box<Error>> {
        // When append becomes stable, use self.content.append() ...
        self.content = try!(parse::construct_bookitems(&self.config.get_src().join("SUMMARY.md")));
        Ok(())
    }

}
<|endoftext|>


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

#[test]
fn no_proxies() {
    let client = new_client();
    let proxies = client.proxies().unwrap();
    assert_eq!(proxies.len(), 0);
}

#[test]
fn proxy_lifecycle() {
    let client = new_client();
    let proxy = Proxy {
        name: "lifecycle".to_string(),
        listen: "127.0.0.1:13306".to_string(),
        upstream: "127.0.0.1:3306".to_string(),
        enabled: true,
    };

    // Create.
    client.create_proxy(&proxy).unwrap();
    let mut exp = HashMap::new();
    exp.insert(proxy.name.to_string(), proxy.clone());
    assert_eq!(exp, client.proxies().unwrap());

    // Update.
    {
        let proxy = exp.get_mut(&proxy.name).unwrap();
        proxy.listen = "127.0.0.1:13307".to_string();
        proxy.upstream = "127.0.0.1:3307".to_string();
        client.update_proxy(proxy).unwrap();
    }
    assert_eq!(exp, client.proxies().unwrap());

    // Delete.
    client.delete_proxy(&proxy.name).unwrap();
    assert_eq!(0, client.proxies().unwrap().len());
}

#[test]
fn unknown_proxy() {
    let client = new_client();
    let proxy = Proxy {
        name: "lifecycle".to_string(),
        listen: "127.0.0.1:13306".to_string(),
        upstream: "127.0.0.1:3306".to_string(),
        enabled: true,
    };

    assert!(client.update_proxy(&proxy).is_err());
    assert!(client.delete_proxy(&proxy.name).is_err());
}

#[test]
fn no_toxics() {
    let client = new_client();
    let proxy = Proxy {
        name: "lifecycle".to_string(),
        listen: "127.0.0.1:13306".to_string(),
        upstream: "127.0.0.1:3306".to_string(),
        enabled: true,
    };

    client.create_proxy(&proxy).unwrap();
    let toxics = client.toxics(&proxy.name).unwrap();
    assert_eq!(0, toxics.len());
}

fn new_client() -> Client {
    let client = Client::new("localhost:8474");
    let proxies = client.proxies().unwrap();

    for name in proxies.keys() {
        client.delete_proxy(name).unwrap();
    }

    client
}
<commit_msg>DRY tests<commit_after>use super::*;
use std::collections::HashMap;

#[test]
fn no_proxies() {
    let client = new_client();
    let proxies = client.proxies().unwrap();
    assert_eq!(proxies.len(), 0);
}

#[test]
fn proxy_lifecycle() {
    let client = new_client();
    let proxy = test_proxy();

    // Create.
    client.create_proxy(&proxy).unwrap();
    let mut exp = HashMap::new();
    exp.insert(proxy.name.to_string(), proxy.clone());
    assert_eq!(exp, client.proxies().unwrap());

    // Update.
    {
        let proxy = exp.get_mut(&proxy.name).unwrap();
        proxy.listen = "127.0.0.1:13307".to_string();
        proxy.upstream = "127.0.0.1:3307".to_string();
        client.update_proxy(proxy).unwrap();
    }
    assert_eq!(exp, client.proxies().unwrap());

    // Delete.
    client.delete_proxy(&proxy.name).unwrap();
    assert_eq!(0, client.proxies().unwrap().len());
}

#[test]
fn unknown_proxy() {
    let client = new_client();
    let proxy = test_proxy();

    assert!(client.update_proxy(&proxy).is_err());
    assert!(client.delete_proxy(&proxy.name).is_err());
}

#[test]
fn no_toxics() {
    let client = new_client();
    let proxy = test_proxy();

    client.create_proxy(&proxy).unwrap();
    let toxics = client.toxics(&proxy.name).unwrap();
    assert_eq!(0, toxics.len());
}

fn new_client() -> Client {
    let client = Client::new("localhost:8474");
    let proxies = client.proxies().unwrap();

    for name in proxies.keys() {
        client.delete_proxy(name).unwrap();
    }

    client
}

fn test_proxy() -> Proxy {
    Proxy {
        name: "testproxy".to_string(),
        listen: "127.0.0.1:13306".to_string(),
        upstream: "127.0.0.1:3306".to_string(),
        enabled: true,
    }
}
<|endoftext|>


<commit_before>//! Possible ZIP compression methods.

/// Compression methods for the contents of a ZIP file.
#[derive(Copy, PartialEq)]
pub enum CompressionMethod
{
    /// The file is stored (no compression)
    Stored,
    /// The file is Deflated
    Deflated,
    /// File is compressed using BZIP2 algorithm
    Bzip2,
    /// Unsupported compression method
    Unsupported(u16),
}

impl CompressionMethod {
    /// Converts an u16 to its corresponding CompressionMethod
    pub fn from_u16(val: u16) -> CompressionMethod {
        match val {
            0 => CompressionMethod::Stored,
            8 => CompressionMethod::Deflated,
            12 => CompressionMethod::Bzip2,
            v => CompressionMethod::Unsupported(v),
        }
    }

    /// Converts a CompressionMethod to a u16
    pub fn to_u16(self) -> u16 {
        match self {
            CompressionMethod::Stored => 0,
            CompressionMethod::Deflated => 8,
            CompressionMethod::Bzip2 => 12,
            CompressionMethod::Unsupported(v) => v,
        }
    }
}

#[cfg(test)]
mod test {
    use super::CompressionMethod;

    #[test]
    fn from_eq_to() {
        for v in (0..::std::u16::MAX as u32 + 1)
        {
            let from = CompressionMethod::from_u16(v as u16);
            let to = from.to_u16() as u32;
            assert_eq!(v, to);
        }
    }

    #[test]
    fn to_eq_from() {
        fn check_match(method: CompressionMethod) {
            let to = method.to_u16();
            let from = CompressionMethod::from_u16(to);
            let back = from.to_u16();
            assert_eq!(to, back);
        }

        check_match(CompressionMethod::Stored);
        check_match(CompressionMethod::Deflated);
        check_match(CompressionMethod::Bzip2);
    }
}
<commit_msg>Derivy Clone where Copy<commit_after>//! Possible ZIP compression methods.

/// Compression methods for the contents of a ZIP file.
#[derive(Copy, Clone, PartialEq)]
pub enum CompressionMethod
{
    /// The file is stored (no compression)
    Stored,
    /// The file is Deflated
    Deflated,
    /// File is compressed using BZIP2 algorithm
    Bzip2,
    /// Unsupported compression method
    Unsupported(u16),
}

impl CompressionMethod {
    /// Converts an u16 to its corresponding CompressionMethod
    pub fn from_u16(val: u16) -> CompressionMethod {
        match val {
            0 => CompressionMethod::Stored,
            8 => CompressionMethod::Deflated,
            12 => CompressionMethod::Bzip2,
            v => CompressionMethod::Unsupported(v),
        }
    }

    /// Converts a CompressionMethod to a u16
    pub fn to_u16(self) -> u16 {
        match self {
            CompressionMethod::Stored => 0,
            CompressionMethod::Deflated => 8,
            CompressionMethod::Bzip2 => 12,
            CompressionMethod::Unsupported(v) => v,
        }
    }
}

#[cfg(test)]
mod test {
    use super::CompressionMethod;

    #[test]
    fn from_eq_to() {
        for v in (0..::std::u16::MAX as u32 + 1)
        {
            let from = CompressionMethod::from_u16(v as u16);
            let to = from.to_u16() as u32;
            assert_eq!(v, to);
        }
    }

    #[test]
    fn to_eq_from() {
        fn check_match(method: CompressionMethod) {
            let to = method.to_u16();
            let from = CompressionMethod::from_u16(to);
            let back = from.to_u16();
            assert_eq!(to, back);
        }

        check_match(CompressionMethod::Stored);
        check_match(CompressionMethod::Deflated);
        check_match(CompressionMethod::Bzip2);
    }
}
<|endoftext|>


<commit_before>//! Aead Ciphers

use crate::crypto::cipher::{CipherCategory, CipherResult, CipherType};

use crate::crypto::ring::RingAeadCipher;
#[cfg(feature = "miscreant")]
use crate::crypto::siv::MiscreantCipher;
#[cfg(feature = "sodium")]
use crate::crypto::sodium::SodiumAeadCipher;

use bytes::{Bytes, BytesMut};
use hkdf::Hkdf;
use sha1::Sha1;

/// Encryptor API for AEAD ciphers
pub trait AeadEncryptor {
    /// Encrypt `input` to `output` with `tag`. `output.len()` should equals to `input.len() + tag.len()`.
    /// ```plain
    /// +----------------------------------------+-----------------------+
    /// | ENCRYPTED TEXT (length = input.len())  | TAG                   |
    /// +----------------------------------------+-----------------------+
    /// ```
    fn encrypt(&mut self, input: &[u8], output: &mut [u8]);
}

/// Decryptor API for AEAD ciphers
pub trait AeadDecryptor {
    /// Decrypt `input` to `output` with `tag`. `output.len()` should equals to `input.len() - tag.len()`.
    /// ```plain
    /// +----------------------------------------+-----------------------+
    /// | ENCRYPTED TEXT (length = output.len()) | TAG                   |
    /// +----------------------------------------+-----------------------+
    /// ```
    fn decrypt(&mut self, input: &[u8], output: &mut [u8]) -> CipherResult<()>;
}

/// Variant `AeadDecryptor`
pub type BoxAeadDecryptor = Box<dyn AeadDecryptor + Send + 'static>;

/// Variant `AeadEncryptor`
pub type BoxAeadEncryptor = Box<dyn AeadEncryptor + Send + 'static>;

/// Generate a specific AEAD cipher encryptor
pub fn new_aead_encryptor(t: CipherType, key: &[u8], nonce: &[u8]) -> BoxAeadEncryptor {
    assert!(t.category() == CipherCategory::Aead);

    match t {
        CipherType::Aes128Gcm | CipherType::Aes256Gcm | CipherType::ChaCha20IetfPoly1305 => {
            Box::new(RingAeadCipher::new(t, key, nonce, true))
        }

        #[cfg(feature = "sodium")]
        CipherType::XChaCha20IetfPoly1305 => Box::new(SodiumAeadCipher::new(t, key, nonce)),

        #[cfg(feature = "miscreant")]
        CipherType::Aes128PmacSiv | CipherType::Aes256PmacSiv => Box::new(MiscreantCipher::new(t, key, nonce)),

        _ => unreachable!(),
    }
}

/// Generate a specific AEAD cipher decryptor
pub fn new_aead_decryptor(t: CipherType, key: &[u8], nonce: &[u8]) -> BoxAeadDecryptor {
    assert!(t.category() == CipherCategory::Aead);

    match t {
        CipherType::Aes128Gcm | CipherType::Aes256Gcm | CipherType::ChaCha20IetfPoly1305 => {
            Box::new(RingAeadCipher::new(t, key, nonce, false))
        }

        #[cfg(feature = "sodium")]
        CipherType::XChaCha20IetfPoly1305 => Box::new(SodiumAeadCipher::new(t, key, nonce)),

        #[cfg(feature = "miscreant")]
        CipherType::Aes128PmacSiv | CipherType::Aes256PmacSiv => Box::new(MiscreantCipher::new(t, key, nonce)),

        _ => unreachable!(),
    }
}

const SUBKEY_INFO: &[u8] = b"ss-subkey";

/// Make Session key
///
/// ## Session key (SIP007)
///
/// AEAD ciphers require a per-session subkey derived from the pre-shared master key using HKDF, and use the subkey
/// to encrypt/decrypt. Essentially it means we are moving from (M+N)-bit (PSK, nonce) pair to
/// (M+N)-bit (HKDF(PSK, salt), nonce) pair. Because HKDF is a PRF, the new construction significantly expands the
/// amount of randomness (from N to at least M where M is much greater than N), thus correcting the previously
/// mentioned design flaw.
///
/// Assuming we already have a user-supplied pre-shared master key PSK.
///
/// Function HKDF_SHA1 is a HKDF constructed using SHA1 hash. Its signature is
///
/// ```plain
/// HKDF_SHA1(secret_key, salt, info)
/// ```
///
/// The "info" string argument allows us to bind the derived subkey to a specific application context.
///
/// For AEAD ciphers, the encryption scheme is:
///
/// 1. Pick a random R-bit salt (R = max(128, len(SK)))
/// 2. Derive subkey SK = HKDF_SHA1(PSK, salt, "ss-subkey")
/// 3. Send salt
/// 4. For each chunk, encrypt and authenticate payload using SK with a counting nonce
///    (starting from 0 and increment by 1 after each use)
/// 5. Send encrypted chunk
pub fn make_skey(t: CipherType, key: &[u8], salt: &[u8]) -> Bytes {
    assert!(t.category() == CipherCategory::Aead);

    let hkdf = Hkdf::<Sha1>::new(Some(salt), key);

    let mut skey = BytesMut::with_capacity(key.len());
    unsafe {
        skey.set_len(key.len());
    }

    hkdf.expand(SUBKEY_INFO, &mut skey).unwrap();

    skey.freeze()
}

/// Increase nonce by 1
///
/// AEAD ciphers requires to increase nonce after encrypt/decrypt every chunk
#[cfg(feature = "sodium")]
pub fn increase_nonce(nonce: &mut [u8]) {
    use libsodium_ffi::sodium_increment;

    unsafe {
        sodium_increment(nonce.as_mut_ptr(), nonce.len());
    }
}

/// Increase nonce by 1
///
/// AEAD ciphers requires to increase nonce after encrypt/decrypt every chunk
#[cfg(not(feature = "sodium"))]
pub fn increase_nonce(nonce: &mut [u8]) {
    let mut prev: u16 = 1;
    for i in nonce {
        prev += *i as u16;
        *i = prev as u8;
        prev >>= 8;
    }
}
<commit_msg>reduce loops and type conversions (#176)<commit_after>//! Aead Ciphers

use crate::crypto::cipher::{CipherCategory, CipherResult, CipherType};

use crate::crypto::ring::RingAeadCipher;
#[cfg(feature = "miscreant")]
use crate::crypto::siv::MiscreantCipher;
#[cfg(feature = "sodium")]
use crate::crypto::sodium::SodiumAeadCipher;

use bytes::{Bytes, BytesMut};
use hkdf::Hkdf;
use sha1::Sha1;

/// Encryptor API for AEAD ciphers
pub trait AeadEncryptor {
    /// Encrypt `input` to `output` with `tag`. `output.len()` should equals to `input.len() + tag.len()`.
    /// ```plain
    /// +----------------------------------------+-----------------------+
    /// | ENCRYPTED TEXT (length = input.len())  | TAG                   |
    /// +----------------------------------------+-----------------------+
    /// ```
    fn encrypt(&mut self, input: &[u8], output: &mut [u8]);
}

/// Decryptor API for AEAD ciphers
pub trait AeadDecryptor {
    /// Decrypt `input` to `output` with `tag`. `output.len()` should equals to `input.len() - tag.len()`.
    /// ```plain
    /// +----------------------------------------+-----------------------+
    /// | ENCRYPTED TEXT (length = output.len()) | TAG                   |
    /// +----------------------------------------+-----------------------+
    /// ```
    fn decrypt(&mut self, input: &[u8], output: &mut [u8]) -> CipherResult<()>;
}

/// Variant `AeadDecryptor`
pub type BoxAeadDecryptor = Box<dyn AeadDecryptor + Send + 'static>;

/// Variant `AeadEncryptor`
pub type BoxAeadEncryptor = Box<dyn AeadEncryptor + Send + 'static>;

/// Generate a specific AEAD cipher encryptor
pub fn new_aead_encryptor(t: CipherType, key: &[u8], nonce: &[u8]) -> BoxAeadEncryptor {
    assert!(t.category() == CipherCategory::Aead);

    match t {
        CipherType::Aes128Gcm | CipherType::Aes256Gcm | CipherType::ChaCha20IetfPoly1305 => {
            Box::new(RingAeadCipher::new(t, key, nonce, true))
        }

        #[cfg(feature = "sodium")]
        CipherType::XChaCha20IetfPoly1305 => Box::new(SodiumAeadCipher::new(t, key, nonce)),

        #[cfg(feature = "miscreant")]
        CipherType::Aes128PmacSiv | CipherType::Aes256PmacSiv => Box::new(MiscreantCipher::new(t, key, nonce)),

        _ => unreachable!(),
    }
}

/// Generate a specific AEAD cipher decryptor
pub fn new_aead_decryptor(t: CipherType, key: &[u8], nonce: &[u8]) -> BoxAeadDecryptor {
    assert!(t.category() == CipherCategory::Aead);

    match t {
        CipherType::Aes128Gcm | CipherType::Aes256Gcm | CipherType::ChaCha20IetfPoly1305 => {
            Box::new(RingAeadCipher::new(t, key, nonce, false))
        }

        #[cfg(feature = "sodium")]
        CipherType::XChaCha20IetfPoly1305 => Box::new(SodiumAeadCipher::new(t, key, nonce)),

        #[cfg(feature = "miscreant")]
        CipherType::Aes128PmacSiv | CipherType::Aes256PmacSiv => Box::new(MiscreantCipher::new(t, key, nonce)),

        _ => unreachable!(),
    }
}

const SUBKEY_INFO: &[u8] = b"ss-subkey";

/// Make Session key
///
/// ## Session key (SIP007)
///
/// AEAD ciphers require a per-session subkey derived from the pre-shared master key using HKDF, and use the subkey
/// to encrypt/decrypt. Essentially it means we are moving from (M+N)-bit (PSK, nonce) pair to
/// (M+N)-bit (HKDF(PSK, salt), nonce) pair. Because HKDF is a PRF, the new construction significantly expands the
/// amount of randomness (from N to at least M where M is much greater than N), thus correcting the previously
/// mentioned design flaw.
///
/// Assuming we already have a user-supplied pre-shared master key PSK.
///
/// Function HKDF_SHA1 is a HKDF constructed using SHA1 hash. Its signature is
///
/// ```plain
/// HKDF_SHA1(secret_key, salt, info)
/// ```
///
/// The "info" string argument allows us to bind the derived subkey to a specific application context.
///
/// For AEAD ciphers, the encryption scheme is:
///
/// 1. Pick a random R-bit salt (R = max(128, len(SK)))
/// 2. Derive subkey SK = HKDF_SHA1(PSK, salt, "ss-subkey")
/// 3. Send salt
/// 4. For each chunk, encrypt and authenticate payload using SK with a counting nonce
///    (starting from 0 and increment by 1 after each use)
/// 5. Send encrypted chunk
pub fn make_skey(t: CipherType, key: &[u8], salt: &[u8]) -> Bytes {
    assert!(t.category() == CipherCategory::Aead);

    let hkdf = Hkdf::<Sha1>::new(Some(salt), key);

    let mut skey = BytesMut::with_capacity(key.len());
    unsafe {
        skey.set_len(key.len());
    }

    hkdf.expand(SUBKEY_INFO, &mut skey).unwrap();

    skey.freeze()
}

/// Increase nonce by 1
///
/// AEAD ciphers requires to increase nonce after encrypt/decrypt every chunk
#[cfg(feature = "sodium")]
pub fn increase_nonce(nonce: &mut [u8]) {
    use libsodium_ffi::sodium_increment;

    unsafe {
        sodium_increment(nonce.as_mut_ptr(), nonce.len());
    }
}

/// Increase nonce by 1
///
/// AEAD ciphers requires to increase nonce after encrypt/decrypt every chunk
#[cfg(not(feature = "sodium"))]
pub fn increase_nonce(nonce: &mut [u8]) {
    for i in nonce {
        if std::u8::MAX == *i {
            *i = 0;
        } else {
            *i += 1;
            return;
        }
    }
}
<|endoftext|>


<commit_before>// error-pattern:Unsatisfied precondition constraint

fn main() {
    let x = 5;
    let _y = fn~(move x) { };
    let _z = x; //< error: Unsatisfied precondition constraint
}
<commit_msg>cap-clause-use-after-move: modernize error msg<commit_after>fn main() {
    let x = 5;
    let _y = fn~(move x) { };
    let _z = x; //~ ERROR use of moved variable: `x`
}
<|endoftext|>