<commit_before>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use bytes::BytesMut;
use citaprotocol::pubsub_message_to_network_message;
use config;
use config::NetConfig;
use libproto::{Message, OperateType};
use notify::DebouncedEvent;
use std::convert::{TryFrom, TryInto};
use std::io::Write;
use std::net::{Shutdown, TcpStream};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::Receiver;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use util::RwLock;

const TIMEOUT: u64 = 15;
// list of peer: id, addr, tcp_connect
type PeerPairs = Arc<RwLock<Vec<(u32, String, Option<TcpStream>)>>>;

/// Manage p2p networks
pub struct Connection {
    pub id_card: u32,
    /// list of peer: id, addr, tcp_connect
    pub peers_pair: PeerPairs,
    pub is_disconnect: Arc<AtomicBool>,
}

impl Connection {
    pub fn new(config: &config::NetConfig) -> Self {
        let id_card = config.id_card.unwrap();
        let mut peers_pair = Vec::default();
        if let Some(peers) = config.peers.as_ref() {
            for peer in peers.iter() {
                let id_card: u32 = peer.id_card.unwrap();
                let addr = format!("{}:{}", peer.ip.clone().unwrap(), peer.port.unwrap());
                peers_pair.push((id_card, addr, None));
            }
        }

        Connection {
            id_card,
            peers_pair: Arc::new(RwLock::new(peers_pair)),
            is_disconnect: Arc::new(AtomicBool::new(false)),
        }
    }

    pub fn is_send(id_card: u32, origin: u32, operate: OperateType) -> bool {
        operate == OperateType::Broadcast
            || (operate == OperateType::Single && id_card == origin)
            || (operate == OperateType::Subtract && origin != id_card)
    }

    pub fn update(&self, config: &config::NetConfig) {
        //添加更新的配置到self
        match config.peers.as_ref() {
            Some(peers) => {
                let mut peers_addr = Vec::new();
                for peer in self.peers_pair.read().iter() {
                    peers_addr.push(peer.1.clone());
                }
                info!("peers before update {:?}", peers_addr);
                let mut config_addr = Vec::new();
                for peer in peers.iter() {
                    let id_card: u32 = peer.id_card.unwrap();
                    let addr = format!("{}:{}", peer.ip.clone().unwrap(), peer.port.unwrap());
                    config_addr.push(addr.clone());
                    if peers_addr.contains(&addr) {
                        continue;
                    }
                    peers_addr.push(addr.clone());
                    self.peers_pair.write().push((id_card, addr, None));
                }
                loop {
                    let index_opt = peers_addr
                        .iter()
                        .position(|addr| !config_addr.contains(addr));
                    if let Some(index) = index_opt {
                        peers_addr.remove(index);
                        self.peers_pair.write().remove(index);
                    } else {
                        break;
                    }
                }
                info!("peers after update {:?}", peers_addr);
            }
            None => {
                info!("clear all peers after update!");
                self.peers_pair.write().clear();
            }
        }
    }

    pub fn broadcast(&self, key: String, mut msg: Message) {
        let origin = msg.get_origin();
        let operate = msg.get_operate();
        msg.set_origin(self.id_card);

        trace!("broadcast msg {:?} from key {}", msg, key);
        let msg_bytes: Vec<u8> = msg.try_into().unwrap();

        let mut buf = BytesMut::with_capacity(4 + 4 + 1 + key.len() + msg_bytes.len());
        pubsub_message_to_network_message(&mut buf, Some((key, msg_bytes)));

        let mut peers = vec![];
        for peer in self.peers_pair.write().iter_mut() {
            if Connection::is_send(peer.0, origin, operate) {
                if let Some(ref mut stream) = peer.2 {
                    peers.push(peer.0);
                    let _ = stream.write(&buf);
                }
            }
        }

        trace!(
            "{:?} broadcast msg to nodes {:?} {:?}",
            self.id_card,
            operate,
            peers
        );
    }

    pub fn broadcast_rawbytes(&self, key: String, data: &[u8]) {
        let mut msg = Message::try_from(data).unwrap();
        self.broadcast(key, msg);
    }
}

fn connect(con: Arc<Connection>) {
    thread::spawn(move || loop {
        for peer in con.peers_pair.write().iter_mut() {
            if con.is_disconnect.load(Ordering::SeqCst) {
                if let Some(ref mut stream) = peer.2 {
                    stream
                        .shutdown(Shutdown::Both)
                        .expect("shutdown call failed");
                }
                peer.2 = None;
                thread::sleep(Duration::from_millis(TIMEOUT * 1000));
                continue;
            }

            let mut need_reconnect = true;
            let mut buf = BytesMut::with_capacity(4 + 4);
            pubsub_message_to_network_message(&mut buf, None);
            if let Some(ref mut stream) = peer.2 {
                let res = stream.write(&buf);
                if res.is_ok() {
                    need_reconnect = false;
                }
            }
            if need_reconnect {
                info!("connect {:?}!", peer.1);
                peer.2 = TcpStream::connect(peer.1.clone()).ok();
            }
        }

        thread::sleep(Duration::from_millis(TIMEOUT * 1000));
        trace!("after sleep retry connect!");
    });
}

pub fn manage_connect(con: &Arc<Connection>, config_path: &str, rx: Receiver<DebouncedEvent>) {
    connect(Arc::clone(con));
    let config = String::from(config_path);

    let con = Arc::clone(con);
    thread::spawn(move || loop {
        match rx.recv() {
            Ok(event) => match event {
                DebouncedEvent::Create(path_buf) | DebouncedEvent::Write(path_buf) => {
                    if path_buf.is_file() {
                        let file_name = path_buf.file_name().unwrap().to_str().unwrap();
                        if file_name == config.as_str() {
                            info!("file {} changed, will auto reload!", file_name);
                            let config = NetConfig::new(config.as_str());
                            con.update(&config);
                        }
                    }
                }
                _ => trace!("file notify event: {:?}", event),
            },
            Err(e) => warn!("watch error: {:?}", e),
        }
    });
}

#[cfg(test)]
mod test {
    use super::Connection;
    use libproto::OperateType;
    #[test]
    fn is_send_msg() {
        assert!(Connection::is_send(0, 0, OperateType::Broadcast));
        assert!(Connection::is_send(0, 1, OperateType::Broadcast));

        assert!(Connection::is_send(0, 0, OperateType::Single));
        assert!(!Connection::is_send(0, 1, OperateType::Single));

        assert!(!Connection::is_send(0, 0, OperateType::Subtract));
        assert!(Connection::is_send(0, 1, OperateType::Subtract));
    }
}
<commit_msg>Shutdown streams when remove peers from the configuration.<commit_after>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use bytes::BytesMut;
use citaprotocol::pubsub_message_to_network_message;
use config;
use config::NetConfig;
use libproto::{Message, OperateType};
use notify::DebouncedEvent;
use std::convert::{TryFrom, TryInto};
use std::io::Write;
use std::net::{Shutdown, TcpStream};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::Receiver;
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use util::RwLock;

const TIMEOUT: u64 = 15;
// list of peer: id, addr, tcp_connect
type PeerPairs = Arc<RwLock<Vec<(u32, String, Option<TcpStream>)>>>;

/// Manage p2p networks
pub struct Connection {
    pub id_card: u32,
    /// list of peer: id, addr, tcp_connect
    pub peers_pair: PeerPairs,
    pub is_disconnect: Arc<AtomicBool>,
}

impl Connection {
    pub fn new(config: &config::NetConfig) -> Self {
        let id_card = config.id_card.unwrap();
        let mut peers_pair = Vec::default();
        if let Some(peers) = config.peers.as_ref() {
            for peer in peers.iter() {
                let id_card: u32 = peer.id_card.unwrap();
                let addr = format!("{}:{}", peer.ip.clone().unwrap(), peer.port.unwrap());
                peers_pair.push((id_card, addr, None));
            }
        }

        Connection {
            id_card,
            peers_pair: Arc::new(RwLock::new(peers_pair)),
            is_disconnect: Arc::new(AtomicBool::new(false)),
        }
    }

    pub fn is_send(id_card: u32, origin: u32, operate: OperateType) -> bool {
        operate == OperateType::Broadcast
            || (operate == OperateType::Single && id_card == origin)
            || (operate == OperateType::Subtract && origin != id_card)
    }

    pub fn update(&self, config: &config::NetConfig) {
        //添加更新的配置到self
        match config.peers.as_ref() {
            Some(peers) => {
                let mut peers_addr = Vec::new();
                for peer in self.peers_pair.read().iter() {
                    peers_addr.push(peer.1.clone());
                }
                info!("peers before update {:?}", peers_addr);
                let mut config_addr = Vec::new();
                for peer in peers.iter() {
                    let id_card: u32 = peer.id_card.unwrap();
                    let addr = format!("{}:{}", peer.ip.clone().unwrap(), peer.port.unwrap());
                    config_addr.push(addr.clone());
                    if peers_addr.contains(&addr) {
                        continue;
                    }
                    peers_addr.push(addr.clone());
                    self.peers_pair.write().push((id_card, addr, None));
                }
                loop {
                    let index_opt = peers_addr
                        .iter()
                        .position(|addr| !config_addr.contains(addr));
                    if let Some(index) = index_opt {
                        peers_addr.remove(index);
                        let (id_card, addr, conn_opt) = self.peers_pair.write().remove(index);
                        conn_opt.map(|ref mut stream| {
                            stream.shutdown(Shutdown::Both).map_err(|err| {
                                warn!("shutdown {} - {} failed: {}", id_card, addr, err);
                            })
                        });
                    } else {
                        break;
                    }
                }
                info!("peers after update {:?}", peers_addr);
            }
            None => {
                info!("clear all peers after update!");
                loop {
                    if let Some((id_card, addr, conn_opt)) = self.peers_pair.write().pop() {
                        conn_opt.map(|ref mut stream| {
                            stream.shutdown(Shutdown::Both).map_err(|err| {
                                warn!("shutdown {} - {} failed: {}", id_card, addr, err);
                            })
                        });
                    } else {
                        break;
                    }
                }
            }
        }
    }

    pub fn broadcast(&self, key: String, mut msg: Message) {
        let origin = msg.get_origin();
        let operate = msg.get_operate();
        msg.set_origin(self.id_card);

        trace!("broadcast msg {:?} from key {}", msg, key);
        let msg_bytes: Vec<u8> = msg.try_into().unwrap();

        let mut buf = BytesMut::with_capacity(4 + 4 + 1 + key.len() + msg_bytes.len());
        pubsub_message_to_network_message(&mut buf, Some((key, msg_bytes)));

        let mut peers = vec![];
        for peer in self.peers_pair.write().iter_mut() {
            if Connection::is_send(peer.0, origin, operate) {
                if let Some(ref mut stream) = peer.2 {
                    peers.push(peer.0);
                    let _ = stream.write(&buf);
                }
            }
        }

        trace!(
            "{:?} broadcast msg to nodes {:?} {:?}",
            self.id_card,
            operate,
            peers
        );
    }

    pub fn broadcast_rawbytes(&self, key: String, data: &[u8]) {
        let mut msg = Message::try_from(data).unwrap();
        self.broadcast(key, msg);
    }
}

fn connect(con: Arc<Connection>) {
    thread::spawn(move || loop {
        for peer in con.peers_pair.write().iter_mut() {
            if con.is_disconnect.load(Ordering::SeqCst) {
                peer.2.as_ref().map(|ref mut stream| {
                    stream.shutdown(Shutdown::Both).map_err(|err| {
                        warn!("shutdown {} - {} failed: {}", peer.0, peer.1, err);
                    });
                });
                peer.2 = None;
                thread::sleep(Duration::from_millis(TIMEOUT * 1000));
                continue;
            }

            let mut need_reconnect = true;
            let mut buf = BytesMut::with_capacity(4 + 4);
            pubsub_message_to_network_message(&mut buf, None);
            if let Some(ref mut stream) = peer.2 {
                let res = stream.write(&buf);
                if res.is_ok() {
                    need_reconnect = false;
                }
            }
            if need_reconnect {
                info!("connect {:?}!", peer.1);
                peer.2 = TcpStream::connect(peer.1.clone()).ok();
            }
        }

        thread::sleep(Duration::from_millis(TIMEOUT * 1000));
        trace!("after sleep retry connect!");
    });
}

pub fn manage_connect(con: &Arc<Connection>, config_path: &str, rx: Receiver<DebouncedEvent>) {
    connect(Arc::clone(con));
    let config = String::from(config_path);

    let con = Arc::clone(con);
    thread::spawn(move || loop {
        match rx.recv() {
            Ok(event) => match event {
                DebouncedEvent::Create(path_buf) | DebouncedEvent::Write(path_buf) => {
                    if path_buf.is_file() {
                        let file_name = path_buf.file_name().unwrap().to_str().unwrap();
                        if file_name == config.as_str() {
                            info!("file {} changed, will auto reload!", file_name);
                            let config = NetConfig::new(config.as_str());
                            con.update(&config);
                        }
                    }
                }
                _ => trace!("file notify event: {:?}", event),
            },
            Err(e) => warn!("watch error: {:?}", e),
        }
    });
}

#[cfg(test)]
mod test {
    use super::Connection;
    use libproto::OperateType;
    #[test]
    fn is_send_msg() {
        assert!(Connection::is_send(0, 0, OperateType::Broadcast));
        assert!(Connection::is_send(0, 1, OperateType::Broadcast));

        assert!(Connection::is_send(0, 0, OperateType::Single));
        assert!(!Connection::is_send(0, 1, OperateType::Single));

        assert!(!Connection::is_send(0, 0, OperateType::Subtract));
        assert!(Connection::is_send(0, 1, OperateType::Subtract));
    }
}
<|endoftext|>


<commit_before>use clap::App;
use clap::Arg;
use clap::ArgMatches;

pub struct DataSampleParser<'a>{
	pub issues: bool,
	opts: ArgMatches<'a>,
}

impl<'a> DataSampleParser<'a> {
	//constructor
	pub fn new() -> DataSampleParser<'a> {
		DataSampleParser{
			issues: false,
			opts: App::new("Test Data Generation")
                          .version("1.0")
                          .author("dsietz")
                          .about("Made just for you!")
                          .arg(Arg::with_name("config")
                               .short("c")
                               .long("config")
                               .value_name("FILE")
                               .help("Specifies the location of the Test Data Generation configuration file (default ./config/tdg.yaml)")
                               .takes_value(true)
                               .default_value("./config/tdg.yaml"))
                          .arg(Arg::with_name("log")
                               .short("l")
                               .long("log")
                               .value_name("FILE")
                               .help("Specifies the location of the log4rs logging configuration file (default ./config/log4rs.yaml)")
                               .takes_value(true)
                               .default_value("./config/log4rs.yaml"))
                          .arg(Arg::with_name("verbose")
                               .short("v")
                               .long("verbose")
                               .possible_values(&["off","info","debug"])
                               .default_value("off")
                               .help("explain what is being done (options: off, info, debug)"))
                          .get_matches(),
		}
	}

	// get() functions
	pub fn get_config_file(&self) -> &str{
		&self.opts.value_of("config").unwrap_or("config/default.yaml")
	}

	pub fn get_log_file(&self) -> &str{
		&self.opts.value_of("log").unwrap_or("config/log4rs.yaml")
	}

	pub fn get_verbos(&self) -> &str{
		&self.opts.value_of("verbose").unwrap_or("false")
	}

	// unique() funcitons
	pub fn runing_with_issues(&self) -> &bool{
		&self.issues
	}
}<commit_msg>working on .travis file<commit_after>use clap::App;
use clap::Arg;
use clap::ArgMatches;

pub struct DataSampleParser<'a>{
	pub issues: bool,
	opts: ArgMatches<'a>,
}

impl<'a> DataSampleParser<'a> {
	//constructor
	pub fn new() -> DataSampleParser<'a> {
		DataSampleParser{
			issues: false,
			opts: App::new("Test Data Generation")
                          .version("1.0")
                          .author("dsietz")
                          .about("Made just for you!")
                          .arg(Arg::with_name("config")
                               .short("c")
                               .long("config")
                               .value_name("FILE")
                               .help("Specifies the location of the Test Data Generation configuration file (default ./config/tdg.yaml)")
                               .takes_value(true)
                               .default_value("./config/tdg.yaml"))
                          .arg(Arg::with_name("log")
                               .short("l")
                               .long("log")
                               .value_name("FILE")
                               .help("Specifies the location of the log4rs logging configuration file (default ./config/log4rs.yaml)")
                               .takes_value(true)
                               .default_value("./config/log4rs.yaml"))
                          .arg(Arg::with_name("verbose")
                               .short("v")
                               .long("verbose")
                               .possible_values(&["off","info","debug"])
                               .default_value("off")
                               .help("explain what is being done (options: off, info, debug)"))
                          .get_matches(),
		}
	}

	// get() functions
	pub fn get_config_file(&self) -> &str{
		&self.opts.value_of("config").unwrap_or("config/default.yaml")
	}

	pub fn get_log_file(&self) -> &str{
		&self.opts.value_of("log").unwrap_or("config/log4rs.yaml")
	}

	pub fn get_verbos(&self) -> &str{
		&self.opts.value_of("verbose").unwrap_or("false")
	}

	// unique() functions
	pub fn runing_with_issues(&self) -> &bool{
		&self.issues
	}
}<|endoftext|>


<commit_before>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// pretty-expanded FIXME #23616

#[cfg(target_arch = "x86")]
pub fn main() { }

#[cfg(target_arch = "x86_64")]
pub fn main() { }

#[cfg(target_arch = "arm")]
pub fn main() { }

#[cfg(target_arch = "aarch64")]
pub fn main() { }

#[cfg(target_arch = "mips")]
pub fn main() { }

#[cfg(target_arch = "mips64")]
pub fn main() { }

#[cfg(target_arch = "powerpc64")]
pub fn main() { }

#[cfg(target_arch = "s390x")]
pub fn main() { }

#[cfg(target_arch = "asmjs")]
pub fn main() { }

#[cfg(target_arch = "wasm32")]
pub fn main() { }

#[cfg(target_arch = "sparc64")]
pub fn main() { }
<commit_msg>Rollup merge of #47719 - malbarbo:run-pass-arch-powerpc, r=alexcrichton<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// pretty-expanded FIXME #23616

#[cfg(target_arch = "x86")]
pub fn main() { }

#[cfg(target_arch = "x86_64")]
pub fn main() { }

#[cfg(target_arch = "arm")]
pub fn main() { }

#[cfg(target_arch = "aarch64")]
pub fn main() { }

#[cfg(target_arch = "mips")]
pub fn main() { }

#[cfg(target_arch = "mips64")]
pub fn main() { }

#[cfg(target_arch = "powerpc")]
pub fn main() { }

#[cfg(target_arch = "powerpc64")]
pub fn main() { }

#[cfg(target_arch = "s390x")]
pub fn main() { }

#[cfg(target_arch = "asmjs")]
pub fn main() { }

#[cfg(target_arch = "wasm32")]
pub fn main() { }

#[cfg(target_arch = "sparc64")]
pub fn main() { }
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use admission_control_proto::proto::admission_control_grpc::{
    create_admission_control, AdmissionControlClient,
};
use admission_control_service::admission_control_service::AdmissionControlService;
use config::config::{NetworkConfig, NodeConfig, RoleType};
use consensus::consensus_provider::{make_consensus_provider, ConsensusProvider};
use crypto::{ed25519::*, ValidKey};
use debug_interface::{node_debug_service::NodeDebugService, proto::node_debug_interface_grpc};
use execution_proto::proto::execution_grpc;
use execution_service::ExecutionService;
use futures::future::{FutureExt, TryFutureExt};
use grpc_helpers::ServerHandle;
use grpcio::{ChannelBuilder, EnvBuilder, ServerBuilder};
use grpcio_sys;
use logger::prelude::*;
use mempool::{proto::mempool_grpc::MempoolClient, MempoolRuntime};
use metrics::metric_server;
use network::{
    validator_network::{
        network_builder::{NetworkBuilder, TransportType},
        LibraNetworkProvider, CONSENSUS_DIRECT_SEND_PROTOCOL, CONSENSUS_RPC_PROTOCOL,
        MEMPOOL_DIRECT_SEND_PROTOCOL, STATE_SYNCHRONIZER_MSG_PROTOCOL,
    },
    NetworkPublicKeys, ProtocolId,
};
use state_synchronizer::StateSynchronizer;
use std::{
    cmp::min,
    convert::{TryFrom, TryInto},
    str::FromStr,
    sync::Arc,
    thread,
    time::Instant,
};
use storage_client::{StorageRead, StorageReadServiceClient, StorageWriteServiceClient};
use storage_service::start_storage_service;
use tokio::runtime::{Builder, Runtime};
use types::account_address::AccountAddress as PeerId;
use vm_validator::vm_validator::VMValidator;

pub struct LibraHandle {
    _ac: ServerHandle,
    _mempool: Option<MempoolRuntime>,
    _state_synchronizer: StateSynchronizer,
    _network_runtimes: Vec<Runtime>,
    consensus: Option<Box<dyn ConsensusProvider>>,
    _execution: ServerHandle,
    _storage: ServerHandle,
    _debug: ServerHandle,
}

impl Drop for LibraHandle {
    fn drop(&mut self) {
        if let Some(consensus) = &mut self.consensus {
            consensus.stop();
        }
    }
}

fn setup_ac(config: &NodeConfig) -> (::grpcio::Server, AdmissionControlClient) {
    let env = Arc::new(
        EnvBuilder::new()
            .name_prefix("grpc-ac-")
            .cq_count(unsafe { min(grpcio_sys::gpr_cpu_num_cores() as usize * 2, 32) })
            .build(),
    );
    let port = config.admission_control.admission_control_service_port;

    // Create mempool client if the node is validator.
    let connection_str = format!("localhost:{}", config.mempool.mempool_service_port);
    let env2 = Arc::new(EnvBuilder::new().name_prefix("grpc-ac-mem-").build());
    let mempool_client = if config.is_validator() {
        Some(Arc::new(MempoolClient::new(
            ChannelBuilder::new(env2).connect(&connection_str),
        )))
    } else {
        None
    };

    // Create storage read client
    let storage_client: Arc<dyn StorageRead> = Arc::new(StorageReadServiceClient::new(
        Arc::new(EnvBuilder::new().name_prefix("grpc-ac-sto-").build()),
        "localhost",
        config.storage.port,
    ));

    let vm_validator = Arc::new(VMValidator::new(&config, Arc::clone(&storage_client)));

    let handle = AdmissionControlService::new(
        mempool_client,
        storage_client,
        vm_validator,
        config
            .admission_control
            .need_to_check_mempool_before_validation,
    );
    let service = create_admission_control(handle);
    let server = ServerBuilder::new(Arc::clone(&env))
        .register_service(service)
        .bind(config.admission_control.address.clone(), port)
        .build()
        .expect("Unable to create grpc server");

    let connection_str = format!("localhost:{}", port);
    let client = AdmissionControlClient::new(ChannelBuilder::new(env).connect(&connection_str));
    (server, client)
}

fn setup_executor(config: &NodeConfig) -> ::grpcio::Server {
    let client_env = Arc::new(EnvBuilder::new().name_prefix("grpc-exe-sto-").build());
    let storage_read_client = Arc::new(StorageReadServiceClient::new(
        Arc::clone(&client_env),
        &config.storage.address,
        config.storage.port,
    ));
    let storage_write_client = Arc::new(StorageWriteServiceClient::new(
        Arc::clone(&client_env),
        &config.storage.address,
        config.storage.port,
        config.storage.grpc_max_receive_len,
    ));

    let handle = ExecutionService::new(storage_read_client, storage_write_client, config);
    let service = execution_grpc::create_execution(handle);
    ::grpcio::ServerBuilder::new(Arc::new(EnvBuilder::new().name_prefix("grpc-exe-").build()))
        .register_service(service)
        .bind(config.execution.address.clone(), config.execution.port)
        .build()
        .expect("Unable to create grpc server")
}

fn setup_debug_interface(config: &NodeConfig) -> ::grpcio::Server {
    let env = Arc::new(EnvBuilder::new().name_prefix("grpc-debug-").build());
    // Start Debug interface
    let debug_service =
        node_debug_interface_grpc::create_node_debug_interface(NodeDebugService::new());
    ::grpcio::ServerBuilder::new(env)
        .register_service(debug_service)
        .bind(
            config.debug_interface.address.clone(),
            config.debug_interface.admission_control_node_debug_port,
        )
        .build()
        .expect("Unable to create grpc server")
}

// TODO(abhayb): Move to network crate (similar to consensus).
pub fn setup_network(
    peer_id: PeerId,
    config: &mut NetworkConfig,
) -> (Runtime, Box<dyn LibraNetworkProvider>) {
    let runtime = Builder::new()
        .name_prefix("network-")
        .build()
        .expect("Failed to start runtime. Won't be able to start networking.");
    let role: RoleType = (&config.role).into();
    let mut network_builder = NetworkBuilder::new(
        runtime.executor(),
        peer_id,
        config.listen_address.clone(),
        role,
    );
    network_builder
        .permissioned(config.is_permissioned)
        .advertised_address(config.advertised_address.clone())
        .direct_send_protocols(vec![
            ProtocolId::from_static(CONSENSUS_DIRECT_SEND_PROTOCOL),
            ProtocolId::from_static(MEMPOOL_DIRECT_SEND_PROTOCOL),
            ProtocolId::from_static(STATE_SYNCHRONIZER_MSG_PROTOCOL),
        ])
        .rpc_protocols(vec![ProtocolId::from_static(CONSENSUS_RPC_PROTOCOL)]);
    if config.is_permissioned {
        // If the node wants to run in permissioned mode, it should also have authentication and
        // encryption.
        assert!(
            config.enable_encryption_and_authentication,
            "Permissioned network end-points should use authentication"
        );
        let trusted_peers = config
            .network_peers
            .peers
            .iter()
            .map(|(peer_id, keys)| {
                (
                    PeerId::from_str(peer_id).unwrap(),
                    NetworkPublicKeys {
                        signing_public_key: keys.network_signing_pubkey.clone(),
                        identity_public_key: keys.network_identity_pubkey.clone(),
                    },
                )
            })
            .collect();
        let seed_peers = config
            .seed_peers
            .seed_peers
            .clone()
            .into_iter()
            .map(|(peer_id, addrs)| (peer_id.try_into().expect("Invalid PeerId"), addrs))
            .collect();
        let network_signing_private = config.network_keypairs.take_network_signing_private()
            .expect("Failed to move network signing private key out of NodeConfig, key not set or moved already");
        let network_signing_public: Ed25519PublicKey = (&network_signing_private).into();
        network_builder
            .transport(TransportType::TcpNoise(Some(
                config.network_keypairs.get_network_identity_keypair(),
            )))
            .connectivity_check_interval_ms(config.connectivity_check_interval_ms)
            .seed_peers(seed_peers)
            .trusted_peers(trusted_peers)
            .signing_keys((network_signing_private, network_signing_public))
            .discovery_interval_ms(config.discovery_interval_ms);
    } else if config.enable_encryption_and_authentication {
        // Even if a network end-point is permissionless, it might want to prove its identity to
        // another peer it connects to. For this, we use TCP + Noise but in a permission-less way.
        network_builder.transport(TransportType::PermissionlessTcpNoise(Some(
            config.network_keypairs.get_network_identity_keypair(),
        )));
    } else {
        network_builder.transport(TransportType::Tcp);
    }
    let (_listen_addr, network_provider) = network_builder.build();
    (runtime, network_provider)
}

pub fn setup_environment(node_config: &mut NodeConfig) -> (AdmissionControlClient, LibraHandle) {
    crash_handler::setup_panic_handler();

    let mut instant = Instant::now();
    let storage = start_storage_service(&node_config);
    debug!(
        "Storage service started in {} ms",
        instant.elapsed().as_millis()
    );

    instant = Instant::now();
    let execution = ServerHandle::setup(setup_executor(&node_config));
    debug!(
        "Execution service started in {} ms",
        instant.elapsed().as_millis()
    );
    let mut network_runtimes = vec![];
    let mut state_sync_network_handles = vec![];
    let mut validator_network_provider = None;

    for mut network in &mut node_config.networks {
        let peer_id = PeerId::try_from(network.peer_id.clone()).expect("Invalid PeerId");
        let (runtime, mut network_provider) = setup_network(peer_id, &mut network);
        state_sync_network_handles.push(network_provider.add_state_synchronizer(vec![
            ProtocolId::from_static(STATE_SYNCHRONIZER_MSG_PROTOCOL),
        ]));
        if let RoleType::Validator = (&network.role).into() {
            validator_network_provider = Some((peer_id, runtime, network_provider));
        } else {
            // For non-validator roles, the peer_id should be derived from the network identity
            // key.
            assert_eq!(
                peer_id,
                PeerId::try_from(
                    network
                        .network_keypairs
                        .get_network_identity_public()
                        .to_bytes()
                )
                .unwrap()
            );
            // Start the network provider.
            runtime
                .executor()
                .spawn(network_provider.start().unit_error().compat());
            network_runtimes.push(runtime);
            debug!("Network started for peer_id: {}", peer_id);
        }
    }
    let state_synchronizer = StateSynchronizer::bootstrap(
        state_sync_network_handles,
        &node_config,
        vec![], // TODO: pass in empty vector for now, will be derived from node config later
    );
    let mut mempool = None;
    let mut consensus = None;
    if let Some((peer_id, runtime, mut network_provider)) = validator_network_provider {
        // Note: We need to start network provider before consensus, because the consensus
        // initialization is blocked on state synchronizer to sync to the initial root ledger
        // info, which in turn cannot make progress before network initialization
        // because the NewPeer events which state synchronizer uses to know its
        // peers are delivered by network provider. If we were to start network
        // provider after consensus, we create a cyclic dependency from
        // network provider -> consensus -> state synchronizer -> network provider. This deadlock
        // was observed in GitHub Issue #749. A long term fix might be make
        // consensus initialization async instead of blocking on state synchronizer.
        let (mempool_network_sender, mempool_network_events) = network_provider
            .add_mempool(vec![ProtocolId::from_static(MEMPOOL_DIRECT_SEND_PROTOCOL)]);
        let (consensus_network_sender, consensus_network_events) =
            network_provider.add_consensus(vec![
                ProtocolId::from_static(CONSENSUS_RPC_PROTOCOL),
                ProtocolId::from_static(CONSENSUS_DIRECT_SEND_PROTOCOL),
            ]);
        runtime
            .executor()
            .spawn(network_provider.start().unit_error().compat());
        network_runtimes.push(runtime);
        debug!("Network started for peer_id: {}", peer_id);

        // Initialize and start mempool.
        instant = Instant::now();
        mempool = Some(MempoolRuntime::bootstrap(
            &node_config,
            mempool_network_sender,
            mempool_network_events,
        ));
        debug!("Mempool started in {} ms", instant.elapsed().as_millis());

        // Initialize and start consensus.
        instant = Instant::now();
        let mut consensus_provider = make_consensus_provider(
            node_config,
            consensus_network_sender,
            consensus_network_events,
            state_synchronizer.create_client(),
        );
        consensus_provider
            .start()
            .expect("Failed to start consensus. Can't proceed.");
        consensus = Some(consensus_provider);
        debug!("Consensus started in {} ms", instant.elapsed().as_millis());
    }

    // Initialize and start AC.
    instant = Instant::now();
    let (ac_server, ac_client) = setup_ac(&node_config);
    let ac = ServerHandle::setup(ac_server);
    debug!("AC started in {} ms", instant.elapsed().as_millis());

    let debug_if = ServerHandle::setup(setup_debug_interface(&node_config));

    let metrics_port = node_config.debug_interface.metrics_server_port;
    let metric_host = node_config.debug_interface.address.clone();
    thread::spawn(move || metric_server::start_server((metric_host.as_str(), metrics_port)));

    let libra_handle = LibraHandle {
        _network_runtimes: network_runtimes,
        _ac: ac,
        _mempool: mempool,
        _state_synchronizer: state_synchronizer,
        consensus,
        _execution: execution,
        _storage: storage,
        _debug: debug_if,
    };
    (ac_client, libra_handle)
}
<commit_msg>[libra-node] change startup order: make metrics and debug start first<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use admission_control_proto::proto::admission_control_grpc::{
    create_admission_control, AdmissionControlClient,
};
use admission_control_service::admission_control_service::AdmissionControlService;
use config::config::{NetworkConfig, NodeConfig, RoleType};
use consensus::consensus_provider::{make_consensus_provider, ConsensusProvider};
use crypto::{ed25519::*, ValidKey};
use debug_interface::{node_debug_service::NodeDebugService, proto::node_debug_interface_grpc};
use execution_proto::proto::execution_grpc;
use execution_service::ExecutionService;
use futures::future::{FutureExt, TryFutureExt};
use grpc_helpers::ServerHandle;
use grpcio::{ChannelBuilder, EnvBuilder, ServerBuilder};
use grpcio_sys;
use logger::prelude::*;
use mempool::{proto::mempool_grpc::MempoolClient, MempoolRuntime};
use metrics::metric_server;
use network::{
    validator_network::{
        network_builder::{NetworkBuilder, TransportType},
        LibraNetworkProvider, CONSENSUS_DIRECT_SEND_PROTOCOL, CONSENSUS_RPC_PROTOCOL,
        MEMPOOL_DIRECT_SEND_PROTOCOL, STATE_SYNCHRONIZER_MSG_PROTOCOL,
    },
    NetworkPublicKeys, ProtocolId,
};
use state_synchronizer::StateSynchronizer;
use std::{
    cmp::min,
    convert::{TryFrom, TryInto},
    str::FromStr,
    sync::Arc,
    thread,
    time::Instant,
};
use storage_client::{StorageRead, StorageReadServiceClient, StorageWriteServiceClient};
use storage_service::start_storage_service;
use tokio::runtime::{Builder, Runtime};
use types::account_address::AccountAddress as PeerId;
use vm_validator::vm_validator::VMValidator;

pub struct LibraHandle {
    _ac: ServerHandle,
    _mempool: Option<MempoolRuntime>,
    _state_synchronizer: StateSynchronizer,
    _network_runtimes: Vec<Runtime>,
    consensus: Option<Box<dyn ConsensusProvider>>,
    _execution: ServerHandle,
    _storage: ServerHandle,
    _debug: ServerHandle,
}

impl Drop for LibraHandle {
    fn drop(&mut self) {
        if let Some(consensus) = &mut self.consensus {
            consensus.stop();
        }
    }
}

fn setup_ac(config: &NodeConfig) -> (::grpcio::Server, AdmissionControlClient) {
    let env = Arc::new(
        EnvBuilder::new()
            .name_prefix("grpc-ac-")
            .cq_count(unsafe { min(grpcio_sys::gpr_cpu_num_cores() as usize * 2, 32) })
            .build(),
    );
    let port = config.admission_control.admission_control_service_port;

    // Create mempool client if the node is validator.
    let connection_str = format!("localhost:{}", config.mempool.mempool_service_port);
    let env2 = Arc::new(EnvBuilder::new().name_prefix("grpc-ac-mem-").build());
    let mempool_client = if config.is_validator() {
        Some(Arc::new(MempoolClient::new(
            ChannelBuilder::new(env2).connect(&connection_str),
        )))
    } else {
        None
    };

    // Create storage read client
    let storage_client: Arc<dyn StorageRead> = Arc::new(StorageReadServiceClient::new(
        Arc::new(EnvBuilder::new().name_prefix("grpc-ac-sto-").build()),
        "localhost",
        config.storage.port,
    ));

    let vm_validator = Arc::new(VMValidator::new(&config, Arc::clone(&storage_client)));

    let handle = AdmissionControlService::new(
        mempool_client,
        storage_client,
        vm_validator,
        config
            .admission_control
            .need_to_check_mempool_before_validation,
    );
    let service = create_admission_control(handle);
    let server = ServerBuilder::new(Arc::clone(&env))
        .register_service(service)
        .bind(config.admission_control.address.clone(), port)
        .build()
        .expect("Unable to create grpc server");

    let connection_str = format!("localhost:{}", port);
    let client = AdmissionControlClient::new(ChannelBuilder::new(env).connect(&connection_str));
    (server, client)
}

fn setup_executor(config: &NodeConfig) -> ::grpcio::Server {
    let client_env = Arc::new(EnvBuilder::new().name_prefix("grpc-exe-sto-").build());
    let storage_read_client = Arc::new(StorageReadServiceClient::new(
        Arc::clone(&client_env),
        &config.storage.address,
        config.storage.port,
    ));
    let storage_write_client = Arc::new(StorageWriteServiceClient::new(
        Arc::clone(&client_env),
        &config.storage.address,
        config.storage.port,
        config.storage.grpc_max_receive_len,
    ));

    let handle = ExecutionService::new(storage_read_client, storage_write_client, config);
    let service = execution_grpc::create_execution(handle);
    ::grpcio::ServerBuilder::new(Arc::new(EnvBuilder::new().name_prefix("grpc-exe-").build()))
        .register_service(service)
        .bind(config.execution.address.clone(), config.execution.port)
        .build()
        .expect("Unable to create grpc server")
}

fn setup_debug_interface(config: &NodeConfig) -> ::grpcio::Server {
    let env = Arc::new(EnvBuilder::new().name_prefix("grpc-debug-").build());
    // Start Debug interface
    let debug_service =
        node_debug_interface_grpc::create_node_debug_interface(NodeDebugService::new());
    ::grpcio::ServerBuilder::new(env)
        .register_service(debug_service)
        .bind(
            config.debug_interface.address.clone(),
            config.debug_interface.admission_control_node_debug_port,
        )
        .build()
        .expect("Unable to create grpc server")
}

// TODO(abhayb): Move to network crate (similar to consensus).
pub fn setup_network(
    peer_id: PeerId,
    config: &mut NetworkConfig,
) -> (Runtime, Box<dyn LibraNetworkProvider>) {
    let runtime = Builder::new()
        .name_prefix("network-")
        .build()
        .expect("Failed to start runtime. Won't be able to start networking.");
    let role: RoleType = (&config.role).into();
    let mut network_builder = NetworkBuilder::new(
        runtime.executor(),
        peer_id,
        config.listen_address.clone(),
        role,
    );
    network_builder
        .permissioned(config.is_permissioned)
        .advertised_address(config.advertised_address.clone())
        .direct_send_protocols(vec![
            ProtocolId::from_static(CONSENSUS_DIRECT_SEND_PROTOCOL),
            ProtocolId::from_static(MEMPOOL_DIRECT_SEND_PROTOCOL),
            ProtocolId::from_static(STATE_SYNCHRONIZER_MSG_PROTOCOL),
        ])
        .rpc_protocols(vec![ProtocolId::from_static(CONSENSUS_RPC_PROTOCOL)]);
    if config.is_permissioned {
        // If the node wants to run in permissioned mode, it should also have authentication and
        // encryption.
        assert!(
            config.enable_encryption_and_authentication,
            "Permissioned network end-points should use authentication"
        );
        let trusted_peers = config
            .network_peers
            .peers
            .iter()
            .map(|(peer_id, keys)| {
                (
                    PeerId::from_str(peer_id).unwrap(),
                    NetworkPublicKeys {
                        signing_public_key: keys.network_signing_pubkey.clone(),
                        identity_public_key: keys.network_identity_pubkey.clone(),
                    },
                )
            })
            .collect();
        let seed_peers = config
            .seed_peers
            .seed_peers
            .clone()
            .into_iter()
            .map(|(peer_id, addrs)| (peer_id.try_into().expect("Invalid PeerId"), addrs))
            .collect();
        let network_signing_private = config.network_keypairs.take_network_signing_private()
            .expect("Failed to move network signing private key out of NodeConfig, key not set or moved already");
        let network_signing_public: Ed25519PublicKey = (&network_signing_private).into();
        network_builder
            .transport(TransportType::TcpNoise(Some(
                config.network_keypairs.get_network_identity_keypair(),
            )))
            .connectivity_check_interval_ms(config.connectivity_check_interval_ms)
            .seed_peers(seed_peers)
            .trusted_peers(trusted_peers)
            .signing_keys((network_signing_private, network_signing_public))
            .discovery_interval_ms(config.discovery_interval_ms);
    } else if config.enable_encryption_and_authentication {
        // Even if a network end-point is permissionless, it might want to prove its identity to
        // another peer it connects to. For this, we use TCP + Noise but in a permission-less way.
        network_builder.transport(TransportType::PermissionlessTcpNoise(Some(
            config.network_keypairs.get_network_identity_keypair(),
        )));
    } else {
        network_builder.transport(TransportType::Tcp);
    }
    let (_listen_addr, network_provider) = network_builder.build();
    (runtime, network_provider)
}

pub fn setup_environment(node_config: &mut NodeConfig) -> (AdmissionControlClient, LibraHandle) {
    crash_handler::setup_panic_handler();

    let mut instant = Instant::now();
    let storage = start_storage_service(&node_config);
    debug!(
        "Storage service started in {} ms",
        instant.elapsed().as_millis()
    );

    instant = Instant::now();
    let execution = ServerHandle::setup(setup_executor(&node_config));
    debug!(
        "Execution service started in {} ms",
        instant.elapsed().as_millis()
    );
    let mut network_runtimes = vec![];
    let mut state_sync_network_handles = vec![];
    let mut validator_network_provider = None;

    for mut network in &mut node_config.networks {
        let peer_id = PeerId::try_from(network.peer_id.clone()).expect("Invalid PeerId");
        let (runtime, mut network_provider) = setup_network(peer_id, &mut network);
        state_sync_network_handles.push(network_provider.add_state_synchronizer(vec![
            ProtocolId::from_static(STATE_SYNCHRONIZER_MSG_PROTOCOL),
        ]));
        if let RoleType::Validator = (&network.role).into() {
            validator_network_provider = Some((peer_id, runtime, network_provider));
        } else {
            // For non-validator roles, the peer_id should be derived from the network identity
            // key.
            assert_eq!(
                peer_id,
                PeerId::try_from(
                    network
                        .network_keypairs
                        .get_network_identity_public()
                        .to_bytes()
                )
                .unwrap()
            );
            // Start the network provider.
            runtime
                .executor()
                .spawn(network_provider.start().unit_error().compat());
            network_runtimes.push(runtime);
            debug!("Network started for peer_id: {}", peer_id);
        }
    }

    let debug_if = ServerHandle::setup(setup_debug_interface(&node_config));

    let metrics_port = node_config.debug_interface.metrics_server_port;
    let metric_host = node_config.debug_interface.address.clone();
    thread::spawn(move || metric_server::start_server((metric_host.as_str(), metrics_port)));

    let state_synchronizer = StateSynchronizer::bootstrap(
        state_sync_network_handles,
        &node_config,
        vec![], // TODO: pass in empty vector for now, will be derived from node config later
    );
    let mut mempool = None;
    let mut consensus = None;
    if let Some((peer_id, runtime, mut network_provider)) = validator_network_provider {
        // Note: We need to start network provider before consensus, because the consensus
        // initialization is blocked on state synchronizer to sync to the initial root ledger
        // info, which in turn cannot make progress before network initialization
        // because the NewPeer events which state synchronizer uses to know its
        // peers are delivered by network provider. If we were to start network
        // provider after consensus, we create a cyclic dependency from
        // network provider -> consensus -> state synchronizer -> network provider. This deadlock
        // was observed in GitHub Issue #749. A long term fix might be make
        // consensus initialization async instead of blocking on state synchronizer.
        let (mempool_network_sender, mempool_network_events) = network_provider
            .add_mempool(vec![ProtocolId::from_static(MEMPOOL_DIRECT_SEND_PROTOCOL)]);
        let (consensus_network_sender, consensus_network_events) =
            network_provider.add_consensus(vec![
                ProtocolId::from_static(CONSENSUS_RPC_PROTOCOL),
                ProtocolId::from_static(CONSENSUS_DIRECT_SEND_PROTOCOL),
            ]);
        runtime
            .executor()
            .spawn(network_provider.start().unit_error().compat());
        network_runtimes.push(runtime);
        debug!("Network started for peer_id: {}", peer_id);

        // Initialize and start mempool.
        instant = Instant::now();
        mempool = Some(MempoolRuntime::bootstrap(
            &node_config,
            mempool_network_sender,
            mempool_network_events,
        ));
        debug!("Mempool started in {} ms", instant.elapsed().as_millis());

        // Initialize and start consensus.
        instant = Instant::now();
        let mut consensus_provider = make_consensus_provider(
            node_config,
            consensus_network_sender,
            consensus_network_events,
            state_synchronizer.create_client(),
        );
        consensus_provider
            .start()
            .expect("Failed to start consensus. Can't proceed.");
        consensus = Some(consensus_provider);
        debug!("Consensus started in {} ms", instant.elapsed().as_millis());
    }

    // Initialize and start AC.
    instant = Instant::now();
    let (ac_server, ac_client) = setup_ac(&node_config);
    let ac = ServerHandle::setup(ac_server);
    debug!("AC started in {} ms", instant.elapsed().as_millis());

    let libra_handle = LibraHandle {
        _network_runtimes: network_runtimes,
        _ac: ac,
        _mempool: mempool,
        _state_synchronizer: state_synchronizer,
        consensus,
        _execution: execution,
        _storage: storage,
        _debug: debug_if,
    };
    (ac_client, libra_handle)
}
<|endoftext|>


<commit_before>pub fn reply(drivel: &str) -> &str {
    "world"
}
<commit_msg>Rust: add example implementation for bob<commit_after>pub fn reply(message: &str) -> &str {
    if is_silence(message) { "Fine. Be that way." }
    else if is_yelling(message) { "Woah, chill out!" }
    else if is_question(message) { "Sure." }
    else  { "Whatever." }
}

fn is_silence(message: &str) -> bool {
    message == ""
}

fn is_yelling(message: &str) -> bool {
    let upcase_message: &[Ascii] = message.to_ascii().to_upper();
    let ascii_message: &[Ascii] = message.to_ascii();
    upcase_message == ascii_message
}

fn is_question(message: &str) -> bool {
    message.ends_with("?")
}
<|endoftext|>


<commit_before>use std::fmt;

pub fn print_result<T: fmt::Debug>(input: &str, rest: &[u8], result: &T) {
    println!(
        "INPUT: {:?}\nLEFT:  {:?}\nRESULT: {:#?}",
        input, rest, result
    );
}

#[macro_export]
macro_rules! assert_parser {
    ($parser:ident, $line:expr, $expectation:expr) => {{
        use std::string::ToString;

        let (rest, parsed) = $parser($line.as_bytes()).unwrap();
        crate::assert::print_result($line, &rest, &parsed);

        assert_eq!(
            parsed, $expectation,
            "{:?} not parsed as expected (leftover: {:?})",
            $line, rest
        );
        assert!(rest.is_empty(), "not parsed completely");

        let serialized = parsed.to_string();
        assert_eq!($line, serialized, "does not reserialize correctly");
        println!("✅");
    }};
}
<commit_msg>env-var gate assert output<commit_after>use std::fmt;

pub fn print_result<T: fmt::Debug>(input: &str, rest: &[u8], result: &T) {
    println!(
        "INPUT: {:?}\nLEFT:  {:?}\nRESULT: {:#?}",
        input, rest, result
    );
}

#[macro_export]
macro_rules! assert_parser {
    ($parser:ident, $line:expr, $expectation:expr) => {{
        use std::string::ToString;

        let (rest, parsed) = $parser($line.as_bytes()).unwrap();
        if std::env::var("VERBOSE_TEST_OUTPUT").is_ok() {
            $crate::assert::print_result($line, &rest, &parsed);
        }
        assert_eq!(
            parsed, $expectation,
            "{:?} not parsed as expected (leftover: {:?})",
            $line, rest
        );
        assert!(rest.is_empty(), "not parsed completely");

        let serialized = parsed.to_string();
        assert_eq!($line, serialized, "does not reserialize correctly");
        println!("✅");
    }};
}
<|endoftext|>


<commit_before>

fn main() {

    println!("Hello, world!");
}
<commit_msg>Need to change data structure for matrix<commit_after>use std::collections::{BTreeMap, BTreeSet};

#[derive(Debug)]
struct Matrix {
    elems: BTreeMap<String, BTreeMap<String, f32>>,
    keys: BTreeSet<String>,
}

impl Matrix {
    fn new() -> Matrix {
        Matrix {
            elems: BTreeMap::new(),
            keys: BTreeSet::new(),
        }
    }

    fn insert(&mut self, c1: &str, c2: &str, val: f32) {
        let mut ins_map = self.elems
            .entry(c1.to_string())
            .or_insert_with(BTreeMap::new);
        ins_map.insert(c2.to_string(), val);
        self.keys.insert(c1.to_string());
        self.keys.insert(c2.to_string());
    }

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

    fn get_d(&self, c1: &str, c2: &str) -> &f32 {
        match self.elems.get(c1) {
            Some(map) => {
                match map.get(c2) {
                    Some(val) => val,
                    None => &self.elems[c2][c1],
                }
            }
            None => {
                match self.elems.get(c2) {
                    Some(map) => {
                        match map.get(c1) {
                            Some(val) => val,
                            None => panic!("c1 wasn't found"),
                        }
                    }
                    None => panic!("c2 wasn't found"),
                }
            }
        }
    }

    fn lowest_d(&self) -> (f32, String, String) {
        let mut iter = self.keys.iter();
        let mut key_1 = match iter.next() {
            Some(val) => val,
            None => panic!("No elements in matrix"),
        };

        let mut lowest = (9999.9, key_1.clone(), key_1.clone());

        for key_2 in iter {
            let &d = self.get_d(key_1, key_2);

            if lowest.0 > d {
                lowest = (d, key_1.clone(), key_2.clone());
            }

            key_1 = key_2;
        }

        lowest
    }

    fn join(&mut self, k1: &str, k2: &str) -> Matrix {
        if !(self.keys.contains(k1) || self.keys.contains(k2)) {
            panic!("Keys aren't in matrix");
        }
        /********************************************************************/
        let var1 = &self.elems[k1];
        let var2 = &self.elems[k2];

        println!("{:?} > {:?}", var1, var2);
        /********************************************************************/
        let d_12 = self.get_d(k1, k2) / 2.0;
        let d_21 = self.get_d(k2, k1) / 2.0;
        println!("D_{}{} / 2 = {}", k1, k2, d_12);
        println!("D_{}{} / 2 = {}", k2, k1, d_21);
        /********************************************************************/
        let mut k = String::from(k1);
        k.push_str(k2);
        let mut elems = self.elems.clone();
        elems.remove(k1);
        elems.remove(k2);

        let mut keys = self.keys.clone();
        keys.remove(k1);
        keys.remove(k2);
        let rem_keys = keys.clone();

        let mut ret_m = Matrix {
            elems: elems,
            keys: keys,
        };

        for key in rem_keys {
            let val = self.get_d(k1, &key) + self.get_d(k2, &key) - self.get_d(k1, k2);
            ret_m.insert(&k, &key, val / 2.0);
        }

        println!("{}", k);

        ret_m
    }

    fn print_matrix(&self) {
        println!("{:#?}", self.elems);
    }
}

fn upgma(input: &[(&str, &str, f32)]) {
    let mut matrix = Matrix::new();

    for &(c1, c2, val) in input {
        matrix.insert(c1, c2, val);
    }

    matrix.print_matrix();
    let (_, key_1, key_2) = matrix.lowest_d();
    println!("Joining: {} and {}", key_1, key_2);
    matrix = matrix.join(&key_1, &key_2);
}

fn main() {
    let input = vec![/*("A", "A", 0.0)0,*/
                     ("A", "B", 10.0),
                     ("A", "C", 12.0),
                     ("A", "D", 10.0),
                     ("A", "E", 7.0),
                     //  ("B", "B", 0.0),
                     ("B", "C", 4.0),
                     ("B", "D", 4.0),
                     ("B", "E", 13.0),
                     //  ("C", "C", 0.0),
                     ("C", "D", 6.0),
                     ("C", "E", 15.0),
                     //  ("D", "D", 0.0),
                     ("D", "E", 13.0) /* ("E", "E", 0.0)*/];

    upgma(&input);
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(docopt_macros)]

extern crate ansi_term;
extern crate docopt;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate nix;
extern crate protobuf;
extern crate record_query;
extern crate rustc_serialize;
extern crate serde_protobuf;

use std::env;
use std::io;
use std::path;

use record_query as rq;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

docopt!(pub Args derive Debug, concat!("
rq - record query v", env!("CARGO_PKG_VERSION"), "

A tool for manipulating data records.

Records are read from stdin, processed, and written to stdout.  The tool accepts
a query in the custom rq query language as its main command-line arguments.

See 'man rq' for in-depth documentation.

Usage:
  rq (--help|--version)
  rq [-j|-c|-p <type>] [-J|-C|-P <type>] [-l <level>|-q] [--] <query>
  rq [-l <level>|-q] protobuf add <schema> [--base <path>]

Options:
  --help
      Show this screen.
  --version
      Show the program name and version.

  -j, --input-json
      Input is white-space separated JSON values.
  -J, --output-json
      Output should be formatted as JSON values.
  -c, --input-cbor
      Input is a series of CBOR values.
  -C, --output-cbor
      Output is a series of CBOR values.
  -p <type>, --input-protobuf <type>
      Input is a single protocol buffer object.  The argument refers to the
      fully qualified name of the message type (including the leading '.').
  -P <type>, --output-protobuf <type>
      Output should be formatted as protocol buffer objects.  The argument
      refers to the fully qualified name of the message type (including the
      leading '.').

  <query>
      A query indicating how to transform each record.

  --base <path>
      Directories are significant when dealing with protocol buffer
      schemas.  This specifies the base directory used to normalize schema
      file paths [default: .]

  -l <level>, --log <level>
      Display log messages at and above the specified log level.  The value can
      be one of 'off', 'error', 'warn', 'info', 'debug' or 'trace'.
  -q, --quiet
      Log nothing (alias for '-l off').
"),
        flag_input_protobuf: Option<String>,
        flag_output_protobuf: Option<String>,
        flag_log: Option<String>,
        flag_base: Option<String>);

fn main() {
    let args: Args = Args::docopt()
                         .version(Some(VERSION.to_owned()))
                         .decode()
                         .unwrap_or_else(|e| e.exit());

    main_with_args(&args).unwrap();
}

fn main_with_args(args: &Args) -> rq::error::Result<()> {
    setup_log(args.flag_log.as_ref().map(String::as_ref), args.flag_quiet);

    let paths = rq::config::Paths::new().unwrap();

    if args.cmd_protobuf {
        if args.cmd_add {
            let schema = path::Path::new(&args.arg_schema);
            let base = path::Path::new(if let Some(ref b) = args.flag_base {
                b.as_str()
            } else {
                "."
            });
            rq::proto_index::add_file(&paths, base, schema)
        } else {
            unreachable!()
        }
    } else {
        run(&args, &paths)
    }
}

fn run(args: &Args, paths: &rq::config::Paths) -> rq::error::Result<()> {

    let stdin = io::stdin();
    let mut input = stdin.lock();

    if let Some(ref name) = args.flag_input_protobuf {
        let proto_descriptors = try!(load_descriptors(&paths));
        let stream = protobuf::CodedInputStream::new(&mut input);
        let source = try!(rq::value::protobuf::source(&proto_descriptors, name, stream));
        run_source(args, paths, source)
    } else if args.flag_input_cbor {
        let source = rq::value::cbor::source(&mut input);
        run_source(args, paths, source)
    } else {
        let source = rq::value::json::source(&mut input);
        run_source(args, paths, source)
    }
}

fn run_source<I>(args: &Args, paths: &rq::config::Paths, source: I) -> rq::error::Result<()>
    where I: rq::value::Source
{
    let mut output = io::stdout();

    if let Some(_) = args.flag_output_protobuf {
        Err(rq::error::Error::unimplemented("protobuf serialization".to_owned()))
    } else if args.flag_output_cbor {
        let sink = rq::value::cbor::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    } else {
        let sink = rq::value::json::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    }
}

fn run_source_sink<I, O>(args: &Args,
                         _paths: &rq::config::Paths,
                         source: I,
                         mut sink: O)
                         -> rq::error::Result<()>
    where I: rq::value::Source,
          O: rq::value::Sink
{
    use record_query::value::Source;

    let query = rq::query::Query::parse(&args.arg_query);
    let query_context = rq::query::Context::new();
    let mut results = try!(query.evaluate(&query_context, source));
    while let Some(result) = try!(results.read()) {
        try!(sink.write(result));
    }
    Ok(())
}

fn load_descriptors(paths: &rq::config::Paths)
                    -> rq::error::Result<serde_protobuf::descriptor::Descriptors> {
    let descriptors_proto = try!(rq::proto_index::compile_descriptor_set(paths));
    Ok(serde_protobuf::descriptor::Descriptors::from_proto(&descriptors_proto))
}

fn setup_log(level: Option<&str>, quiet: bool) {
    use std::str::FromStr;
    use ansi_term::ANSIStrings;
    use ansi_term::Colour;
    use ansi_term::Style;
    use log::LogLevel;
    use log::LogLevelFilter;
    use nix::unistd;
    use nix::sys::ioctl;

    let normal = Style::new();

    let format = move |record: &log::LogRecord| {
        if unistd::isatty(ioctl::libc::STDERR_FILENO).unwrap_or(false) {
            let (front, back) = match record.level() {
                LogLevel::Error => (Colour::Red.normal(), Colour::Red.dimmed()),
                LogLevel::Warn => (Colour::Yellow.normal(), Colour::Yellow.dimmed()),
                LogLevel::Info => (Colour::Blue.normal(), Colour::Blue.dimmed()),
                LogLevel::Debug => (Colour::Purple.normal(), Colour::Purple.dimmed()),
                LogLevel::Trace => (Colour::White.dimmed(), Colour::Black.normal()),
            };

            let strings = &[back.paint("["),
                            front.paint(format!("{}", record.level())),
                            back.paint("]"),
                            normal.paint(" "),
                            back.paint("["),
                            front.paint(record.location().module_path()),
                            back.paint("]"),
                            normal.paint(" "),
                            back.paint(format!("{}", record.args()))];

            format!("{}", ANSIStrings(strings))
        } else {
            format!("[{}] [{}] {}",
                    record.level(),
                    record.location().module_path(),
                    record.args())
        }
    };

    let mut builder = env_logger::LogBuilder::new();

    let filter = if quiet {
        LogLevelFilter::Off
    } else if let Some(l) = level {
        LogLevelFilter::from_str(l).unwrap_or(LogLevelFilter::Info)
    } else {
        LogLevelFilter::Info
    };

    builder.format(format).filter(None, filter);

    if let Ok(spec) = env::var("RUST_LOG") {
        builder.parse(&spec);
    }

    builder.init().unwrap();
}

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

    fn parse_args(args: &[&str]) -> Args {
        let a = Args::docopt().argv(args).decode().unwrap();
        println!("{:?}", a);
        a
    }

    #[test]
    fn test_docopt_kitchen_sink() {
        let a = parse_args(&["rq", "-l", "info", "-jP", ".foo.Bar", "select x"]);
        assert!(a.flag_input_json);
        assert_eq!(a.flag_output_protobuf, Some(".foo.Bar".to_owned()));
        assert_eq!(a.flag_log, Some("info".to_owned()));
        assert_eq!(a.arg_query, "select x");
    }

    #[test]
    fn test_docopt_no_args() {
        parse_args(&["rq"]);
    }

    #[test]
    #[should_panic(expected = "Help")]
    fn test_docopt_help() {
        parse_args(&["rq", "--help"]);
    }

    #[test]
    fn test_docopt_version() {
        let a = parse_args(&["rq", "--version"]);
        assert!(a.flag_version);
    }

    #[test]
    fn test_docopt_input_json() {
        let a = parse_args(&["rq", "-j"]);
        assert!(a.flag_input_json);
    }

    #[test]
    fn test_docopt_input_json_long() {
        let a = parse_args(&["rq", "--input-json"]);
        assert!(a.flag_input_json);
    }

    #[test]
    fn test_docopt_output_json() {
        let a = parse_args(&["rq", "-J"]);
        assert!(a.flag_output_json);
    }

    #[test]
    fn test_docopt_output_json_long() {
        let a = parse_args(&["rq", "--output-json"]);
        assert!(a.flag_output_json);
    }

    #[test]
    fn test_docopt_input_cbor() {
        let a = parse_args(&["rq", "-c"]);
        assert!(a.flag_input_cbor);
    }

    #[test]
    fn test_docopt_input_cbor_long() {
        let a = parse_args(&["rq", "--input-cbor"]);
        assert!(a.flag_input_cbor);
    }

    #[test]
    fn test_docopt_output_cbor() {
        let a = parse_args(&["rq", "-C"]);
        assert!(a.flag_output_cbor);
    }

    #[test]
    fn test_docopt_output_cbor_long() {
        let a = parse_args(&["rq", "--output-cbor"]);
        assert!(a.flag_output_cbor);
    }

    #[test]
    fn test_docopt_input_protobuf() {
        let a = parse_args(&["rq", "-p", ".foo.Bar"]);
        assert_eq!(a.flag_input_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    fn test_docopt_input_protobuf_long() {
        let a = parse_args(&["rq", "--input-protobuf", ".foo.Bar"]);
        assert_eq!(a.flag_input_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    fn test_docopt_output_protobuf() {
        let a = parse_args(&["rq", "-P", ".foo.Bar"]);
        assert_eq!(a.flag_output_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    fn test_docopt_output_protobuf_long() {
        let a = parse_args(&["rq", "--output-protobuf", ".foo.Bar"]);
        assert_eq!(a.flag_output_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    #[should_panic(expected = "NoMatch")]
    fn test_docopt_input_conflict() {
        parse_args(&["rq", "-jc"]);
    }

    #[test]
    #[should_panic(expected = "NoMatch")]
    fn test_docopt_output_conflict() {
        parse_args(&["rq", "-JC"]);
    }

    #[test]
    fn test_docopt_protobuf_add_schema() {
        let a = parse_args(&["rq", "-l", "info", "protobuf", "add", "schema.proto"]);
        assert_eq!(a.flag_log, Some("info".to_owned()));
        assert!(a.cmd_protobuf);
        assert!(a.cmd_add);
        assert_eq!(a.arg_schema, "schema.proto");
    }
}
<commit_msg>Make query optional again and default to 'id'<commit_after>#![feature(plugin)]
#![plugin(docopt_macros)]

extern crate ansi_term;
extern crate docopt;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate nix;
extern crate protobuf;
extern crate record_query;
extern crate rustc_serialize;
extern crate serde_protobuf;

use std::env;
use std::io;
use std::path;

use record_query as rq;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

docopt!(pub Args derive Debug, concat!("
rq - record query v", env!("CARGO_PKG_VERSION"), "

A tool for manipulating data records.

Records are read from stdin, processed, and written to stdout.  The tool accepts
a query in the custom rq query language as its main command-line arguments.

See 'man rq' for in-depth documentation.

Usage:
  rq (--help|--version)
  rq [-j|-c|-p <type>] [-J|-C|-P <type>] [-l <level>|-q] [--] [<query>]
  rq [-l <level>|-q] protobuf add <schema> [--base <path>]

Options:
  --help
      Show this screen.
  --version
      Show the program name and version.

  -j, --input-json
      Input is white-space separated JSON values.
  -J, --output-json
      Output should be formatted as JSON values.
  -c, --input-cbor
      Input is a series of CBOR values.
  -C, --output-cbor
      Output is a series of CBOR values.
  -p <type>, --input-protobuf <type>
      Input is a single protocol buffer object.  The argument refers to the
      fully qualified name of the message type (including the leading '.').
  -P <type>, --output-protobuf <type>
      Output should be formatted as protocol buffer objects.  The argument
      refers to the fully qualified name of the message type (including the
      leading '.').

  <query>
      A query indicating how to transform each record.

  --base <path>
      Directories are significant when dealing with protocol buffer
      schemas.  This specifies the base directory used to normalize schema
      file paths [default: .]

  -l <level>, --log <level>
      Display log messages at and above the specified log level.  The value can
      be one of 'off', 'error', 'warn', 'info', 'debug' or 'trace'.
  -q, --quiet
      Log nothing (alias for '-l off').
"),
        flag_input_protobuf: Option<String>,
        flag_output_protobuf: Option<String>,
        flag_log: Option<String>,
        flag_base: Option<String>);

fn main() {
    let args: Args = Args::docopt()
        .version(Some(VERSION.to_owned()))
        .decode()
        .unwrap_or_else(|e| e.exit());

    main_with_args(&args).unwrap();
}

fn main_with_args(args: &Args) -> rq::error::Result<()> {
    setup_log(args.flag_log.as_ref().map(String::as_ref), args.flag_quiet);

    let paths = rq::config::Paths::new().unwrap();

    if args.cmd_protobuf {
        if args.cmd_add {
            let schema = path::Path::new(&args.arg_schema);
            let base = path::Path::new(if let Some(ref b) = args.flag_base {
                b.as_str()
            } else {
                "."
            });
            rq::proto_index::add_file(&paths, base, schema)
        } else {
            unreachable!()
        }
    } else {
        run(&args, &paths)
    }
}

fn run(args: &Args, paths: &rq::config::Paths) -> rq::error::Result<()> {

    let stdin = io::stdin();
    let mut input = stdin.lock();

    if let Some(ref name) = args.flag_input_protobuf {
        let proto_descriptors = try!(load_descriptors(&paths));
        let stream = protobuf::CodedInputStream::new(&mut input);
        let source = try!(rq::value::protobuf::source(&proto_descriptors, name, stream));
        run_source(args, paths, source)
    } else if args.flag_input_cbor {
        let source = rq::value::cbor::source(&mut input);
        run_source(args, paths, source)
    } else {
        let source = rq::value::json::source(&mut input);
        run_source(args, paths, source)
    }
}

fn run_source<I>(args: &Args, paths: &rq::config::Paths, source: I) -> rq::error::Result<()>
    where I: rq::value::Source
{
    let mut output = io::stdout();

    if let Some(_) = args.flag_output_protobuf {
        Err(rq::error::Error::unimplemented("protobuf serialization".to_owned()))
    } else if args.flag_output_cbor {
        let sink = rq::value::cbor::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    } else {
        let sink = rq::value::json::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    }
}

fn run_source_sink<I, O>(args: &Args,
                         _paths: &rq::config::Paths,
                         source: I,
                         mut sink: O)
                         -> rq::error::Result<()>
    where I: rq::value::Source,
          O: rq::value::Sink
{
    use record_query::value::Source;

    let query = rq::query::Query::parse(if args.arg_query.is_empty() {
        "id"
    } else {
        &args.arg_query
    });
    let query_context = rq::query::Context::new();
    let mut results = try!(query.evaluate(&query_context, source));
    while let Some(result) = try!(results.read()) {
        try!(sink.write(result));
    }
    Ok(())
}

fn load_descriptors(paths: &rq::config::Paths)
                    -> rq::error::Result<serde_protobuf::descriptor::Descriptors> {
    let descriptors_proto = try!(rq::proto_index::compile_descriptor_set(paths));
    Ok(serde_protobuf::descriptor::Descriptors::from_proto(&descriptors_proto))
}

fn setup_log(level: Option<&str>, quiet: bool) {
    use std::str::FromStr;
    use ansi_term::ANSIStrings;
    use ansi_term::Colour;
    use ansi_term::Style;
    use log::LogLevel;
    use log::LogLevelFilter;
    use nix::unistd;
    use nix::sys::ioctl;

    let normal = Style::new();

    let format = move |record: &log::LogRecord| {
        if unistd::isatty(ioctl::libc::STDERR_FILENO).unwrap_or(false) {
            let (front, back) = match record.level() {
                LogLevel::Error => (Colour::Red.normal(), Colour::Red.dimmed()),
                LogLevel::Warn => (Colour::Yellow.normal(), Colour::Yellow.dimmed()),
                LogLevel::Info => (Colour::Blue.normal(), Colour::Blue.dimmed()),
                LogLevel::Debug => (Colour::Purple.normal(), Colour::Purple.dimmed()),
                LogLevel::Trace => (Colour::White.dimmed(), Colour::Black.normal()),
            };

            let strings = &[back.paint("["),
                            front.paint(format!("{}", record.level())),
                            back.paint("]"),
                            normal.paint(" "),
                            back.paint("["),
                            front.paint(record.location().module_path()),
                            back.paint("]"),
                            normal.paint(" "),
                            back.paint(format!("{}", record.args()))];

            format!("{}", ANSIStrings(strings))
        } else {
            format!("[{}] [{}] {}",
                    record.level(),
                    record.location().module_path(),
                    record.args())
        }
    };

    let mut builder = env_logger::LogBuilder::new();

    let filter = if quiet {
        LogLevelFilter::Off
    } else if let Some(l) = level {
        LogLevelFilter::from_str(l).unwrap_or(LogLevelFilter::Info)
    } else {
        LogLevelFilter::Info
    };

    builder.format(format).filter(None, filter);

    if let Ok(spec) = env::var("RUST_LOG") {
        builder.parse(&spec);
    }

    builder.init().unwrap();
}

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

    fn parse_args(args: &[&str]) -> Args {
        let a = Args::docopt().argv(args).decode().unwrap();
        println!("{:?}", a);
        a
    }

    #[test]
    fn test_docopt_kitchen_sink() {
        let a = parse_args(&["rq", "-l", "info", "-jP", ".foo.Bar", "select x"]);
        assert!(a.flag_input_json);
        assert_eq!(a.flag_output_protobuf, Some(".foo.Bar".to_owned()));
        assert_eq!(a.flag_log, Some("info".to_owned()));
        assert_eq!(a.arg_query, "select x");
    }

    #[test]
    fn test_docopt_no_args() {
        parse_args(&["rq"]);
    }

    #[test]
    #[should_panic(expected = "Help")]
    fn test_docopt_help() {
        parse_args(&["rq", "--help"]);
    }

    #[test]
    fn test_docopt_version() {
        let a = parse_args(&["rq", "--version"]);
        assert!(a.flag_version);
    }

    #[test]
    fn test_docopt_input_json() {
        let a = parse_args(&["rq", "-j"]);
        assert!(a.flag_input_json);
    }

    #[test]
    fn test_docopt_input_json_long() {
        let a = parse_args(&["rq", "--input-json"]);
        assert!(a.flag_input_json);
    }

    #[test]
    fn test_docopt_output_json() {
        let a = parse_args(&["rq", "-J"]);
        assert!(a.flag_output_json);
    }

    #[test]
    fn test_docopt_output_json_long() {
        let a = parse_args(&["rq", "--output-json"]);
        assert!(a.flag_output_json);
    }

    #[test]
    fn test_docopt_input_cbor() {
        let a = parse_args(&["rq", "-c"]);
        assert!(a.flag_input_cbor);
    }

    #[test]
    fn test_docopt_input_cbor_long() {
        let a = parse_args(&["rq", "--input-cbor"]);
        assert!(a.flag_input_cbor);
    }

    #[test]
    fn test_docopt_output_cbor() {
        let a = parse_args(&["rq", "-C"]);
        assert!(a.flag_output_cbor);
    }

    #[test]
    fn test_docopt_output_cbor_long() {
        let a = parse_args(&["rq", "--output-cbor"]);
        assert!(a.flag_output_cbor);
    }

    #[test]
    fn test_docopt_input_protobuf() {
        let a = parse_args(&["rq", "-p", ".foo.Bar"]);
        assert_eq!(a.flag_input_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    fn test_docopt_input_protobuf_long() {
        let a = parse_args(&["rq", "--input-protobuf", ".foo.Bar"]);
        assert_eq!(a.flag_input_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    fn test_docopt_output_protobuf() {
        let a = parse_args(&["rq", "-P", ".foo.Bar"]);
        assert_eq!(a.flag_output_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    fn test_docopt_output_protobuf_long() {
        let a = parse_args(&["rq", "--output-protobuf", ".foo.Bar"]);
        assert_eq!(a.flag_output_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    #[should_panic(expected = "NoMatch")]
    fn test_docopt_input_conflict() {
        parse_args(&["rq", "-jc"]);
    }

    #[test]
    #[should_panic(expected = "NoMatch")]
    fn test_docopt_output_conflict() {
        parse_args(&["rq", "-JC"]);
    }

    #[test]
    fn test_docopt_protobuf_add_schema() {
        let a = parse_args(&["rq", "-l", "info", "protobuf", "add", "schema.proto"]);
        assert_eq!(a.flag_log, Some("info".to_owned()));
        assert!(a.cmd_protobuf);
        assert!(a.cmd_add);
        assert_eq!(a.arg_schema, "schema.proto");
    }
}
<|endoftext|>