<commit_before>use ::crypto::Hash;
use ::messages::{RawMessage, Precommit, BlockProof};
use ::storage::{StorageValue, ListTable, MapTable, MerkleTable, MerklePatriciaTable, HeightBytes,
                Error, Map, List, RootProofNode};

use super::{Block, Blockchain};
use super::config::StoredConfiguration;

pub type ConfigurationData = Vec<u8>;

type StorageView = ::storage::View;

pub struct Schema<'a> {
    view: &'a StorageView,
}

impl<'a> Schema<'a> {
    pub fn new(view: &'a StorageView) -> Schema {
        Schema { view: view }
    }

    pub fn transactions(&self) -> MapTable<StorageView, Hash, RawMessage> {
        MapTable::new(vec![00], self.view)
    }

    pub fn blocks(&self) -> MapTable<StorageView, Hash, Block> {
        MapTable::new(vec![01], self.view)
    }

    pub fn heights(&self) -> ListTable<MapTable<StorageView, [u8], Vec<u8>>, u64, Hash> {
        ListTable::new(MapTable::new(vec![02], self.view))
    }

    pub fn block_txs(&self,
                     height: u64)
                     -> MerkleTable<MapTable<StorageView, [u8], Vec<u8>>, u32, Hash> {
        MerkleTable::new(MapTable::new([&[03u8] as &[u8], &height.serialize()].concat(), self.view))
    }

    pub fn precommits(&self,
                      hash: &Hash)
                      -> ListTable<MapTable<StorageView, [u8], Vec<u8>>, u32, Precommit> {
        ListTable::new(MapTable::new([&[03], hash.as_ref()].concat(), self.view))
    }

    pub fn block_and_precommits(&self, height: u64) -> Result<Option<BlockProof>, Error> {
        let block_hash = match self.heights().get(height)? {
            None => return Ok(None),
            Some(block_hash) => block_hash,
        };
        let block = self.blocks().get(&block_hash)?.unwrap();
        let precommits_table = self.precommits(&block_hash);
        let precommits = precommits_table.values()?;
        let res = BlockProof {
            block: block,
            precommits: precommits,
        };
        Ok(Some(res))
    }

    pub fn configs
        (&self)
         -> MerklePatriciaTable<MapTable<StorageView, [u8], Vec<u8>>, HeightBytes, ConfigurationData> {
        // configs patricia merkletree <высота блока> json
        MerklePatriciaTable::new(MapTable::new(vec![06], self.view))
    }

    // TODO: consider List index to reduce storage volume
    pub fn configs_heights(&self)
                           -> ListTable<MapTable<StorageView, [u8], Vec<u8>>, u64, HeightBytes> {
        ListTable::new(MapTable::new(vec![07], self.view))
    }

    pub fn state_hash_aggregator(&self)
                            -> MerklePatriciaTable<MapTable<StorageView, [u8], Vec<u8>>, Hash, Hash> {
        MerklePatriciaTable::new(MapTable::new(vec![08], self.view))
    }

    pub fn last_block(&self) -> Result<Option<Block>, Error> {
        Ok(match self.heights().last()? {
            Some(hash) => Some(self.blocks().get(&hash)?.unwrap()),
            None => None,
        })
    }

    pub fn last_height(&self) -> Result<u64, Error> {
        self.last_block().map(|block| block.unwrap().height())
    }

    pub fn commit_actual_configuration(&self,
                                       actual_from: u64,
                                       config_data: &[u8])
                                       -> Result<(), Error> {
        let height_bytecode = actual_from.into();
        self.configs().put(&height_bytecode, config_data.to_vec())?;
        self.configs_heights().append(height_bytecode)?;
        // TODO: clear storages
        Ok(())
    }

    pub fn get_actual_configurations_height(&self) -> Result<u64, Error> {
        // TODO improve perfomance
        let h = self.last_height()? + 1;
        let heights = self.configs_heights();
        let height_values = heights.values().unwrap();

        let idx = height_values.into_iter()
            .rposition(|r| u64::from(r) <= h)
            .unwrap();
        let height = heights.get(idx as u64)?.unwrap();
        Ok(height.into())
    }

    pub fn get_actual_configuration(&self) -> Result<StoredConfiguration, Error> {
        let height = self.get_actual_configurations_height()?;
        self.get_configuration_at_height(height).map(|x| x.unwrap())
    }

    // FIXME Replace by result?
    pub fn get_configuration_at_height(&self,
                                       height: u64)
                                       -> Result<Option<StoredConfiguration>, Error> {
        let configs = self.configs();
        if let Some(config) = configs.get(&height.into())? {
            match StoredConfiguration::deserialize(&config) {
                Ok(configuration) => {
                    return Ok(Some(configuration));
                }
                Err(_) => {
                    error!("Can't parse found configuration at height: {}", height);
                }
            }
        }
        Ok(None)
    }

    pub fn core_state_hash(&self) -> Result<Vec<Hash>, Error> {
        Ok(vec![self.configs().root_hash()?])
    }

    pub fn get_proof_to_service_table(&self, service_id: u16, table_idx: usize) -> Result<RootProofNode<Hash>, Error>
    {
        let key = Blockchain::service_table_unique_key(service_id, table_idx);
        let sum_table = self.state_hash_aggregator();
        sum_table.construct_path_to_key(key)
    }
}<commit_msg>Fix get_actual_configurations_height<commit_after>use ::crypto::Hash;
use ::messages::{RawMessage, Precommit, BlockProof};
use ::storage::{StorageValue, ListTable, MapTable, MerkleTable, MerklePatriciaTable, HeightBytes,
                Error, Map, List, RootProofNode};

use super::{Block, Blockchain};
use super::config::StoredConfiguration;

pub type ConfigurationData = Vec<u8>;

type StorageView = ::storage::View;

pub struct Schema<'a> {
    view: &'a StorageView,
}

impl<'a> Schema<'a> {
    pub fn new(view: &'a StorageView) -> Schema {
        Schema { view: view }
    }

    pub fn transactions(&self) -> MapTable<StorageView, Hash, RawMessage> {
        MapTable::new(vec![00], self.view)
    }

    pub fn blocks(&self) -> MapTable<StorageView, Hash, Block> {
        MapTable::new(vec![01], self.view)
    }

    pub fn heights(&self) -> ListTable<MapTable<StorageView, [u8], Vec<u8>>, u64, Hash> {
        ListTable::new(MapTable::new(vec![02], self.view))
    }

    pub fn block_txs(&self,
                     height: u64)
                     -> MerkleTable<MapTable<StorageView, [u8], Vec<u8>>, u32, Hash> {
        MerkleTable::new(MapTable::new([&[03u8] as &[u8], &height.serialize()].concat(), self.view))
    }

    pub fn precommits(&self,
                      hash: &Hash)
                      -> ListTable<MapTable<StorageView, [u8], Vec<u8>>, u32, Precommit> {
        ListTable::new(MapTable::new([&[03], hash.as_ref()].concat(), self.view))
    }

    pub fn block_and_precommits(&self, height: u64) -> Result<Option<BlockProof>, Error> {
        let block_hash = match self.heights().get(height)? {
            None => return Ok(None),
            Some(block_hash) => block_hash,
        };
        let block = self.blocks().get(&block_hash)?.unwrap();
        let precommits_table = self.precommits(&block_hash);
        let precommits = precommits_table.values()?;
        let res = BlockProof {
            block: block,
            precommits: precommits,
        };
        Ok(Some(res))
    }

    pub fn configs
        (&self)
         -> MerklePatriciaTable<MapTable<StorageView, [u8], Vec<u8>>, HeightBytes, ConfigurationData> {
        // configs patricia merkletree <высота блока> json
        MerklePatriciaTable::new(MapTable::new(vec![06], self.view))
    }

    // TODO: consider List index to reduce storage volume
    pub fn configs_heights(&self)
                           -> ListTable<MapTable<StorageView, [u8], Vec<u8>>, u64, HeightBytes> {
        ListTable::new(MapTable::new(vec![07], self.view))
    }

    pub fn state_hash_aggregator(&self)
                            -> MerklePatriciaTable<MapTable<StorageView, [u8], Vec<u8>>, Hash, Hash> {
        MerklePatriciaTable::new(MapTable::new(vec![08], self.view))
    }

    pub fn last_block(&self) -> Result<Option<Block>, Error> {
        Ok(match self.heights().last()? {
            Some(hash) => Some(self.blocks().get(&hash)?.unwrap()),
            None => None,
        })
    }

    pub fn last_height(&self) -> Result<u64, Error> {
        self.last_block().map(|block| block.unwrap().height())
    }

    pub fn commit_actual_configuration(&self,
                                       actual_from: u64,
                                       config_data: &[u8])
                                       -> Result<(), Error> {
        let height_bytecode = actual_from.into();
        self.configs().put(&height_bytecode, config_data.to_vec())?;
        self.configs_heights().append(height_bytecode)?;
        // TODO: clear storages
        Ok(())
    }

    pub fn get_actual_configurations_height(&self) -> Result<u64, Error> {
        // TODO improve perfomance
        let h = self.last_height()? + 1;
        let heights = self.configs_heights();
        let height_values = heights.values().unwrap();

        let idx = height_values.into_iter()
            .rposition(|r| u64::from(r) <= h)
            .unwrap();
        Ok(idx as u64)
    }

    pub fn get_actual_configuration(&self) -> Result<StoredConfiguration, Error> {
        let height = self.get_actual_configurations_height()?;
        self.get_configuration_at_height(height).map(|x| x.unwrap())
    }

    // FIXME Replace by result?
    pub fn get_configuration_at_height(&self,
                                       height: u64)
                                       -> Result<Option<StoredConfiguration>, Error> {
        let configs = self.configs();
        if let Some(config) = configs.get(&height.into())? {
            match StoredConfiguration::deserialize(&config) {
                Ok(configuration) => {
                    return Ok(Some(configuration));
                }
                Err(_) => {
                    error!("Can't parse found configuration at height: {}", height);
                }
            }
        }
        Ok(None)
    }

    pub fn core_state_hash(&self) -> Result<Vec<Hash>, Error> {
        Ok(vec![self.configs().root_hash()?])
    }

    pub fn get_proof_to_service_table(&self, service_id: u16, table_idx: usize) -> Result<RootProofNode<Hash>, Error>
    {
        let key = Blockchain::service_table_unique_key(service_id, table_idx);
        let sum_table = self.state_hash_aggregator();
        sum_table.construct_path_to_key(key)
    }
}<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

#[feature(globs)];
#[feature(macro_rules)];

#[link(name = "benchmark", vers = "alpha", author = "dwrensha")];

#[crate_type = "bin"];

extern mod capnprust;

pub mod common;

pub mod carsales_capnp;
pub mod carsales;

pub mod catrank_capnp;
pub mod catrank;

pub mod eval_capnp;
pub mod eval;

mod Uncompressed {
    use capnprust;
    use std;

    pub fn write<T : std::io::Writer>(writer: &mut T,
                                          message: &capnprust::message::MessageBuilder) {
        capnprust::serialize::writeMessage(writer, message);
    }

    pub fn newReader<U : std::io::Reader, T>(
        inputStream : &mut U,
        options : capnprust::message::ReaderOptions,
        cont : &fn(v : &mut capnprust::message::MessageReader) -> T) -> T {
        capnprust::serialize::InputStreamMessageReader::new(inputStream, options, cont)
    }

    pub fn newBufferedReader<R: std::io::Reader, T>(
        inputStream : &mut capnprust::io::BufferedInputStream<R>,
        options : capnprust::message::ReaderOptions,
        cont : &fn(v : &mut capnprust::message::MessageReader) -> T) -> T {
        capnprust::serialize::InputStreamMessageReader::new(inputStream, options, cont)
    }
}

mod Packed {
    use capnprust;
    use std;
    use capnprust::serialize_packed::{WritePackedWrapper, WritePacked};

    pub fn write<T : std::io::Writer>(writer: &mut T,
                                          message: &capnprust::message::MessageBuilder) {
        let mut w = WritePackedWrapper{writer: writer};
        w.writePackedMessage(message);
    }

    pub fn newReader<U : std::io::Reader, T>(
        inputStream : &mut U,
        options : capnprust::message::ReaderOptions,
        cont : &fn(v : &mut capnprust::message::MessageReader) -> T) -> T {
        capnprust::serialize::InputStreamMessageReader::new(
            &mut capnprust::serialize_packed::PackedInputStream{
                inner : &mut capnprust::io::BufferedInputStream::new(inputStream)
            },
            options, cont)
    }

    pub fn newBufferedReader<R:std::io::Reader, T>(
        inputStream : &mut capnprust::io::BufferedInputStream<R>,
        options : capnprust::message::ReaderOptions,
        cont : &fn(v : &mut capnprust::message::MessageReader) -> T) -> T {
        capnprust::serialize::InputStreamMessageReader::new(
            &mut capnprust::serialize_packed::PackedInputStream{
                inner : inputStream
            },
            options, cont)
    }

}

macro_rules! passByObject(
    ( $testcase:ident, $iters:expr ) => ({
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let mut messageReq = capnprust::message::MessageBuilder::new_default();
                let mut messageRes = capnprust::message::MessageBuilder::new_default();

                let request = messageReq.initRoot::<$testcase::RequestBuilder>();
                let response = messageRes.initRoot::<$testcase::ResponseBuilder>();
                let expected = $testcase::setupRequest(&mut rng, request);

                do request.asReader |requestReader| {
                    $testcase::handleRequest(requestReader, response);
                }

                do response.asReader |responseReader| {
                    if (! $testcase::checkResponse(responseReader, expected)) {
                        fail!("Incorrect response.");
                    }
                }
            }
        });
    )

macro_rules! passByBytes(
    ( $testcase:ident, $compression:ident, $iters:expr ) => ({
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let mut messageReq = capnprust::message::MessageBuilder::new_default();
                let mut messageRes = capnprust::message::MessageBuilder::new_default();

                let request = messageReq.initRoot::<$testcase::RequestBuilder>();
                let response = messageRes.initRoot::<$testcase::ResponseBuilder>();
                let expected = $testcase::setupRequest(&mut rng, request);

                let requestBytes = do std::io::mem::with_mem_writer |writer| {
                    $compression::write(writer, messageReq)
                };

                do $compression::newReader(
                      &mut std::io::mem::BufReader::new(requestBytes),
                      capnprust::message::DEFAULT_READER_OPTIONS) |requestReader| {
                    let requestReader = $testcase::newRequestReader(requestReader.getRoot());
                    $testcase::handleRequest(requestReader, response);
                }

                let responseBytes = do std::io::mem::with_mem_writer |writer| {
                    $compression::write(writer, messageRes);
                };

                do $compression::newReader(
                    &mut std::io::mem::BufReader::new(responseBytes),
                    capnprust::message::DEFAULT_READER_OPTIONS) |responseReader| {
                    let responseReader = $testcase::newResponseReader(responseReader.getRoot());
                    if (! $testcase::checkResponse(responseReader, expected)) {
                        fail!("Incorrect response.");
                    }
                }
            }
        });
    )

macro_rules! server(
    ( $testcase:ident, $compression:ident, $iters:expr, $input:expr, $output:expr) => ({
            let mut outBuffered = capnprust::io::BufferedOutputStream::new(&mut $output);
            let mut inBuffered = capnprust::io::BufferedInputStream::new(&mut $input);
            for _ in range(0, $iters) {
                let mut messageRes = capnprust::message::MessageBuilder::new_default();
                let response = messageRes.initRoot::<$testcase::ResponseBuilder>();
                do $compression::newBufferedReader(
                    &mut inBuffered,
                    capnprust::message::DEFAULT_READER_OPTIONS) |requestReader| {
                    let requestReader = $testcase::newRequestReader(requestReader.getRoot());
                    $testcase::handleRequest(requestReader, response);
                }
                $compression::write(&mut outBuffered, messageRes);
                outBuffered.flush();
            }
        });
    )

macro_rules! syncClient(
    ( $testcase:ident, $compression:ident, $iters:expr) => ({
            let mut outStream = std::io::stdout();
            let mut outBuffered = capnprust::io::BufferedOutputStream::new(&mut outStream);
            let mut inStream = std::io::stdin();
            let mut inBuffered = capnprust::io::BufferedInputStream::new(&mut inStream);
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let mut messageReq = capnprust::message::MessageBuilder::new_default();
                let request = messageReq.initRoot::<$testcase::RequestBuilder>();

                let expected = $testcase::setupRequest(&mut rng, request);
                $compression::write(&mut outBuffered, messageReq);
                outBuffered.flush();

                do $compression::newBufferedReader(
                    &mut inBuffered,
                    capnprust::message::DEFAULT_READER_OPTIONS) |responseReader| {
                    let responseReader = $testcase::newResponseReader(responseReader.getRoot());
                    assert!($testcase::checkResponse(responseReader, expected));
                }

            }
        });
    )

macro_rules! passByPipe(
    ( $testcase:ident, $compression:ident, $iters:expr) => ({
            use std::io::process;

            // get a rustc crash if we put this in line below
            let io = ~[process::CreatePipe(true, false), // stdin
                       process::CreatePipe(false, true), // stdout
                       process::Ignored];

            let mut args = std::os::args();
            args[2] = ~"client";

            let config = process::ProcessConfig {
                program: "./benchmark/benchmark",
                args: args.slice(1, args.len()),
                env : None,
                cwd: None,
                io : io
            };
            match process::Process::new(config) {
                Some(ref mut p) => {
                    p.io.pop();
                    let mut childStdOut = p.io.pop();
                    let mut childStdIn = p.io.pop();

                    server!($testcase, $compression, $iters, childStdOut, childStdIn);
                    println!("{}", p.wait());
                }
                None => {
                    println("bummer");
                }
            }
        });
    )

macro_rules! doTestcase(
    ( $testcase:ident, $mode:expr, $reuse:expr, $compression:ident, $iters:expr ) => ({
            match $mode {
                ~"object" => passByObject!($testcase, $iters),
                ~"bytes" => passByBytes!($testcase, $compression, $iters),
                ~"client" => syncClient!($testcase, $compression, $iters),
                ~"pipe" => passByPipe!($testcase, $compression, $iters),
                s => fail!("unrecognized mode: {}", s)
            }
        });
    )

macro_rules! doTestcase1(
    ( $testcase:expr, $mode:expr, $reuse:expr, $compression:ident, $iters:expr) => ({
            match $testcase {
                ~"carsales" => doTestcase!(carsales, $mode, $reuse, $compression, $iters),
                ~"catrank" => doTestcase!(catrank, $mode, $reuse, $compression, $iters),
                ~"eval" => doTestcase!(eval, $mode, $reuse, $compression, $iters),
                s => fail!("unrecognized test case: {}", s)
            }
        });
    )

pub fn main () {

    let args = std::os::args();

    if (args.len() != 6) {
        println!("USAGE: {} CASE MODE REUSE COMPRESSION ITERATION_COUNT", args[0]);
        std::os::set_exit_status(1);
        return;
    }

    let iters = match from_str::<u64>(args[5]) {
        Some (n) => n,
        None => {
            println!("Could not parse a u64 from: {}", args[5]);
            std::os::set_exit_status(1);
            return;
        }
    };

    // For now, just insist that re-use = none
    match args[3] {
        ~"no-reuse" => {}
        _ => fail!("for now, 'no-reuse' is the only allowed option for REUSE")
    }

    match args[4] {
        ~"none" => doTestcase1!(args[1], args[2],  args[3], Uncompressed, iters),
        ~"packed" => doTestcase1!(args[1], args[2], args[3], Packed, iters),
        s => fail!("unrecognized compression: {}", s)
    }

}
<commit_msg>use scratch space for passbybytes writers<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

#[feature(globs)];
#[feature(macro_rules)];

#[link(name = "benchmark", vers = "alpha", author = "dwrensha")];

#[crate_type = "bin"];

extern mod capnprust;

pub mod common;

pub mod carsales_capnp;
pub mod carsales;

pub mod catrank_capnp;
pub mod catrank;

pub mod eval_capnp;
pub mod eval;

mod Uncompressed {
    use capnprust;
    use std;

    pub fn write<T : std::io::Writer>(writer: &mut T,
                                          message: &capnprust::message::MessageBuilder) {
        capnprust::serialize::writeMessage(writer, message);
    }

    pub fn newReader<U : std::io::Reader, T>(
        inputStream : &mut U,
        options : capnprust::message::ReaderOptions,
        cont : &fn(v : &mut capnprust::message::MessageReader) -> T) -> T {
        capnprust::serialize::InputStreamMessageReader::new(inputStream, options, cont)
    }

    pub fn newBufferedReader<R: std::io::Reader, T>(
        inputStream : &mut capnprust::io::BufferedInputStream<R>,
        options : capnprust::message::ReaderOptions,
        cont : &fn(v : &mut capnprust::message::MessageReader) -> T) -> T {
        capnprust::serialize::InputStreamMessageReader::new(inputStream, options, cont)
    }
}

mod Packed {
    use capnprust;
    use std;
    use capnprust::serialize_packed::{WritePackedWrapper, WritePacked};

    pub fn write<T : std::io::Writer>(writer: &mut T,
                                          message: &capnprust::message::MessageBuilder) {
        let mut w = WritePackedWrapper{writer: writer};
        w.writePackedMessage(message);
    }

    pub fn newReader<U : std::io::Reader, T>(
        inputStream : &mut U,
        options : capnprust::message::ReaderOptions,
        cont : &fn(v : &mut capnprust::message::MessageReader) -> T) -> T {
        capnprust::serialize::InputStreamMessageReader::new(
            &mut capnprust::serialize_packed::PackedInputStream{
                inner : &mut capnprust::io::BufferedInputStream::new(inputStream)
            },
            options, cont)
    }

    pub fn newBufferedReader<R:std::io::Reader, T>(
        inputStream : &mut capnprust::io::BufferedInputStream<R>,
        options : capnprust::message::ReaderOptions,
        cont : &fn(v : &mut capnprust::message::MessageReader) -> T) -> T {
        capnprust::serialize::InputStreamMessageReader::new(
            &mut capnprust::serialize_packed::PackedInputStream{
                inner : inputStream
            },
            options, cont)
    }

}

macro_rules! passByObject(
    ( $testcase:ident, $iters:expr ) => ({
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let mut messageReq = capnprust::message::MessageBuilder::new_default();
                let mut messageRes = capnprust::message::MessageBuilder::new_default();

                let request = messageReq.initRoot::<$testcase::RequestBuilder>();
                let response = messageRes.initRoot::<$testcase::ResponseBuilder>();
                let expected = $testcase::setupRequest(&mut rng, request);

                do request.asReader |requestReader| {
                    $testcase::handleRequest(requestReader, response);
                }

                do response.asReader |responseReader| {
                    if (! $testcase::checkResponse(responseReader, expected)) {
                        fail!("Incorrect response.");
                    }
                }
            }
        });
    )

static SCRATCH_SIZE : uint = 128 * 1024;
//static scratchSpace : [u8, .. 6 * SCRATCH_SIZE] = [0, .. 6 * SCRATCH_SIZE];

macro_rules! passByBytes(
    ( $testcase:ident, $compression:ident, $iters:expr ) => ({
            let mut requestBytes : [u8, .. SCRATCH_SIZE] = [0, .. SCRATCH_SIZE];
            let mut responseBytes : [u8, .. SCRATCH_SIZE] = [0, .. SCRATCH_SIZE];
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let mut messageReq = capnprust::message::MessageBuilder::new_default();
                let mut messageRes = capnprust::message::MessageBuilder::new_default();

                let request = messageReq.initRoot::<$testcase::RequestBuilder>();
                let response = messageRes.initRoot::<$testcase::ResponseBuilder>();
                let expected = $testcase::setupRequest(&mut rng, request);

                {
                    let mut writer = std::io::mem::BufWriter::new(requestBytes);
                    $compression::write(&mut writer, messageReq)
                }

                do $compression::newReader(
                      &mut std::io::mem::BufReader::new(requestBytes),
                      capnprust::message::DEFAULT_READER_OPTIONS) |requestReader| {
                    let requestReader = $testcase::newRequestReader(requestReader.getRoot());
                    $testcase::handleRequest(requestReader, response);
                }

                {
                    let mut writer = std::io::mem::BufWriter::new(responseBytes);
                    $compression::write(&mut writer, messageRes)
                }

                do $compression::newReader(
                    &mut std::io::mem::BufReader::new(responseBytes),
                    capnprust::message::DEFAULT_READER_OPTIONS) |responseReader| {
                    let responseReader = $testcase::newResponseReader(responseReader.getRoot());
                    if (! $testcase::checkResponse(responseReader, expected)) {
                        fail!("Incorrect response.");
                    }
                }
            }
        });
    )

macro_rules! server(
    ( $testcase:ident, $compression:ident, $iters:expr, $input:expr, $output:expr) => ({
            let mut outBuffered = capnprust::io::BufferedOutputStream::new(&mut $output);
            let mut inBuffered = capnprust::io::BufferedInputStream::new(&mut $input);
            for _ in range(0, $iters) {
                let mut messageRes = capnprust::message::MessageBuilder::new_default();
                let response = messageRes.initRoot::<$testcase::ResponseBuilder>();
                do $compression::newBufferedReader(
                    &mut inBuffered,
                    capnprust::message::DEFAULT_READER_OPTIONS) |requestReader| {
                    let requestReader = $testcase::newRequestReader(requestReader.getRoot());
                    $testcase::handleRequest(requestReader, response);
                }
                $compression::write(&mut outBuffered, messageRes);
                outBuffered.flush();
            }
        });
    )

macro_rules! syncClient(
    ( $testcase:ident, $compression:ident, $iters:expr) => ({
            let mut outStream = std::io::stdout();
            let mut outBuffered = capnprust::io::BufferedOutputStream::new(&mut outStream);
            let mut inStream = std::io::stdin();
            let mut inBuffered = capnprust::io::BufferedInputStream::new(&mut inStream);
            let mut rng = common::FastRand::new();
            for _ in range(0, $iters) {
                let mut messageReq = capnprust::message::MessageBuilder::new_default();
                let request = messageReq.initRoot::<$testcase::RequestBuilder>();

                let expected = $testcase::setupRequest(&mut rng, request);
                $compression::write(&mut outBuffered, messageReq);
                outBuffered.flush();

                do $compression::newBufferedReader(
                    &mut inBuffered,
                    capnprust::message::DEFAULT_READER_OPTIONS) |responseReader| {
                    let responseReader = $testcase::newResponseReader(responseReader.getRoot());
                    assert!($testcase::checkResponse(responseReader, expected));
                }

            }
        });
    )

macro_rules! passByPipe(
    ( $testcase:ident, $compression:ident, $iters:expr) => ({
            use std::io::process;

            // get a rustc crash if we put this in line below
            let io = ~[process::CreatePipe(true, false), // stdin
                       process::CreatePipe(false, true), // stdout
                       process::Ignored];

            let mut args = std::os::args();
            args[2] = ~"client";

            let config = process::ProcessConfig {
                program: "./benchmark/benchmark",
                args: args.slice(1, args.len()),
                env : None,
                cwd: None,
                io : io
            };
            match process::Process::new(config) {
                Some(ref mut p) => {
                    p.io.pop();
                    let mut childStdOut = p.io.pop();
                    let mut childStdIn = p.io.pop();

                    server!($testcase, $compression, $iters, childStdOut, childStdIn);
                    println!("{}", p.wait());
                }
                None => {
                    println("bummer");
                }
            }
        });
    )

macro_rules! doTestcase(
    ( $testcase:ident, $mode:expr, $reuse:expr, $compression:ident, $iters:expr ) => ({
            match $mode {
                ~"object" => passByObject!($testcase, $iters),
                ~"bytes" => passByBytes!($testcase, $compression, $iters),
                ~"client" => syncClient!($testcase, $compression, $iters),
                ~"pipe" => passByPipe!($testcase, $compression, $iters),
                s => fail!("unrecognized mode: {}", s)
            }
        });
    )

macro_rules! doTestcase1(
    ( $testcase:expr, $mode:expr, $reuse:expr, $compression:ident, $iters:expr) => ({
            match $testcase {
                ~"carsales" => doTestcase!(carsales, $mode, $reuse, $compression, $iters),
                ~"catrank" => doTestcase!(catrank, $mode, $reuse, $compression, $iters),
                ~"eval" => doTestcase!(eval, $mode, $reuse, $compression, $iters),
                s => fail!("unrecognized test case: {}", s)
            }
        });
    )

pub fn main () {

    let args = std::os::args();

    if (args.len() != 6) {
        println!("USAGE: {} CASE MODE REUSE COMPRESSION ITERATION_COUNT", args[0]);
        std::os::set_exit_status(1);
        return;
    }

    let iters = match from_str::<u64>(args[5]) {
        Some (n) => n,
        None => {
            println!("Could not parse a u64 from: {}", args[5]);
            std::os::set_exit_status(1);
            return;
        }
    };

    // For now, just insist that re-use = none
    match args[3] {
        ~"no-reuse" => {}
        _ => fail!("for now, 'no-reuse' is the only allowed option for REUSE")
    }

    match args[4] {
        ~"none" => doTestcase1!(args[1], args[2],  args[3], Uncompressed, iters),
        ~"packed" => doTestcase1!(args[1], args[2], args[3], Packed, iters),
        s => fail!("unrecognized compression: {}", s)
    }

}
<|endoftext|>


<commit_before><commit_msg>script for backfilling the advertiser attribute<commit_after><|endoftext|>


<commit_before>use std::os::unix::process::CommandExt;
use std::process::Command;

const SYSTEMD_RUN: &'static str = "/usr/bin/systemd-run";
const FIREJAIL: &'static str = "/usr/bin/firejail";

const FIREFOX: &'static str = "/usr/bin/firefox";
const FIREFOX_PROFILE: &'static str = "/etc/firejail/firefox.profile";
const FIREFOX_MOZILLA_SFW_PROFILE: &'static str = "default-1473025815439";

const KEIRA: &'static str = "/home/kalvin/Downloads/.firefox-nightly/firefox";
const KEIRA_PROFILE: &'static str = "/etc/firejail/firefox-nightly.profile";

const TERM: &'static str = "/usr/bin/alacritty";
const TERM_PROFILE: &'static str = "/etc/firejail/x-terminal-emulator.profile";

const THUNDERBIRD: &'static str = "/home/kalvin/Downloads/.thunderbird-beta/thunderbird";
const THUNDERBIRD_PROFILE: &'static str = "/etc/firejail/thunderbird-beta.profile";

#[derive(Debug)]
struct CgroupedFirejailedCommandOptions<'a> {
    bin_path: &'a str,
    memory_high: Option<i32>,
    memory_max: Option<i32>,
    firejail_profile: Option<&'a str>,
    implicit_extra_args: Option<&'a [&'a str]>,
    argv_remainder: std::env::Args,
}

fn cgrouped_firejail_command(options: CgroupedFirejailedCommandOptions) -> Command {
    let mut command = Command::new(SYSTEMD_RUN);
    command.args(&["--user", "--scope"]);
    command.args(&["-p", "MemorySwapMax=0"]);

    if let Some(memory_high) = options.memory_high {
        let memory_high_owned_string = format!("MemoryHigh={}M", memory_high);
        command.args(&["-p", memory_high_owned_string.as_str()]);
    }
    if let Some(memory_max) = options.memory_max {
        let memory_max_owned_string = format!("MemoryMax={}M", memory_max);
        command.args(&["-p", memory_max_owned_string.as_str()]);
    }

    if let Some(firejail_profile) = options.firejail_profile {
        command.arg(FIREJAIL);
        command.arg("--ignore=seccomp");
        command.arg(format!("--profile={}", firejail_profile));
    }

    command.arg(options.bin_path);

    if let Some(implicit_extra_args) = options.implicit_extra_args {
        command.args(implicit_extra_args);
    }

    let argv_remainder: Vec<String> = options.argv_remainder.collect();
    command.args(argv_remainder);

    command
}

fn simple_firejail_command(target: &str, args: std::env::Args) -> Command {
    let mut command = Command::new(FIREJAIL);

    command.arg(format!("--profile=/etc/firejail/{}.profile", target));
    command.arg(format!("/usr/bin/{}", target));

    let argv_remainder: Vec<String> = args.collect();
    command.args(argv_remainder);

    command
}

fn init_command() -> Command {
    let mut args = std::env::args();
    args.next();

    let target = args.next().unwrap();
    match target.as_str() {
        "ff" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: FIREFOX,
                memory_high: Some(4420),
                memory_max: Some(5200),
                firejail_profile: Some(FIREFOX_PROFILE),
                implicit_extra_args: Some(&["-P", FIREFOX_MOZILLA_SFW_PROFILE]),
                argv_remainder: args,
            });
        }
        "keira" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: KEIRA,
                memory_high: Some(4420),
                memory_max: Some(5200),
                firejail_profile: Some(KEIRA_PROFILE),
                implicit_extra_args: Some(&["-P", "nightly"]),
                argv_remainder: args,
            });
        }
        "npv" => return simple_firejail_command("mpv", args),
        "t" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: TERM,
                memory_high: None,
                memory_max: None,
                firejail_profile: Some(TERM_PROFILE),
                implicit_extra_args: None,
                argv_remainder: args,
            })
        }
        "tbb" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: THUNDERBIRD,
                memory_high: None,
                memory_max: None,
                firejail_profile: Some(THUNDERBIRD_PROFILE),
                implicit_extra_args: None,
                argv_remainder: args,
            });
        }
        "vlk" => return simple_firejail_command("vlc", args),
        "z" => return simple_firejail_command("zathura", args),
        _ => panic!(format!("no handler for ``{}''", target)),
    }
}

fn main() {
    let mut command = init_command();
    println!("{:#?}", command);
    command.exec();
}
<commit_msg>unner: copy argv<commit_after>use std::os::unix::process::CommandExt;
use std::process::Command;

const SYSTEMD_RUN: &'static str = "/usr/bin/systemd-run";
const FIREJAIL: &'static str = "/usr/bin/firejail";

const FIREFOX: &'static str = "/usr/bin/firefox";
const FIREFOX_PROFILE: &'static str = "/etc/firejail/firefox.profile";
const FIREFOX_MOZILLA_SFW_PROFILE: &'static str = "default-1473025815439";

const KEIRA: &'static str = "/home/kalvin/Downloads/.firefox-nightly/firefox";
const KEIRA_PROFILE: &'static str = "/etc/firejail/firefox-nightly.profile";

const TERM: &'static str = "/usr/bin/alacritty";
const TERM_PROFILE: &'static str = "/etc/firejail/x-terminal-emulator.profile";

const THUNDERBIRD: &'static str = "/home/kalvin/Downloads/.thunderbird-beta/thunderbird";
const THUNDERBIRD_PROFILE: &'static str = "/etc/firejail/thunderbird-beta.profile";

#[derive(Debug)]
struct CgroupedFirejailedCommandOptions<'a> {
    bin_path: &'a str,
    memory_high: Option<i32>,
    memory_max: Option<i32>,
    firejail_profile: Option<&'a str>,
    implicit_extra_args: Option<&'a [&'a str]>,
    argv_remainder: Vec<String>,
}

fn cgrouped_firejail_command(options: CgroupedFirejailedCommandOptions) -> Command {
    let mut command = Command::new(SYSTEMD_RUN);
    command.args(&["--user", "--scope"]);
    command.args(&["-p", "MemorySwapMax=0"]);

    if let Some(memory_high) = options.memory_high {
        let memory_high_owned_string = format!("MemoryHigh={}M", memory_high);
        command.args(&["-p", memory_high_owned_string.as_str()]);
    }
    if let Some(memory_max) = options.memory_max {
        let memory_max_owned_string = format!("MemoryMax={}M", memory_max);
        command.args(&["-p", memory_max_owned_string.as_str()]);
    }

    if let Some(firejail_profile) = options.firejail_profile {
        command.arg(FIREJAIL);
        command.arg("--ignore=seccomp");
        command.arg(format!("--profile={}", firejail_profile));
    }

    command.arg(options.bin_path);

    if let Some(implicit_extra_args) = options.implicit_extra_args {
        command.args(implicit_extra_args);
    }

    command.args(options.argv_remainder);

    command
}

fn simple_firejail_command(target: &str, args: Vec<String>) -> Command {
    let mut command = Command::new(FIREJAIL);

    command.arg(format!("--profile=/etc/firejail/{}.profile", target));
    command.arg(format!("/usr/bin/{}", target));
    command.args(args);

    command
}

fn init_command() -> Command {
    let mut args_less_the_first = std::env::args();
    // Pops the name of this executable.
    args_less_the_first.next();

    // Pops the name of the unner target.
    let target = args_less_the_first.next().unwrap();

    // Copies and collects the remaining argv.
    let args: Vec<String> = args_less_the_first.collect();

    match target.as_str() {
        "ff" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: FIREFOX,
                memory_high: Some(4420),
                memory_max: Some(5200),
                firejail_profile: Some(FIREFOX_PROFILE),
                implicit_extra_args: Some(&["-P", FIREFOX_MOZILLA_SFW_PROFILE]),
                argv_remainder: args,
            });
        }
        "keira" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: KEIRA,
                memory_high: Some(4420),
                memory_max: Some(5200),
                firejail_profile: Some(KEIRA_PROFILE),
                implicit_extra_args: Some(&["-P", "nightly"]),
                argv_remainder: args,
            });
        }
        "npv" => return simple_firejail_command("mpv", args),
        "t" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: TERM,
                memory_high: None,
                memory_max: None,
                firejail_profile: Some(TERM_PROFILE),
                implicit_extra_args: None,
                argv_remainder: args,
            })
        }
        "tbb" => {
            return cgrouped_firejail_command(CgroupedFirejailedCommandOptions {
                bin_path: THUNDERBIRD,
                memory_high: None,
                memory_max: None,
                firejail_profile: Some(THUNDERBIRD_PROFILE),
                implicit_extra_args: None,
                argv_remainder: args,
            });
        }
        "vlk" => return simple_firejail_command("vlc", args),
        "z" => return simple_firejail_command("zathura", args),
        _ => panic!(format!("no handler for ``{}''", target)),
    }
}

fn main() {
    let mut command = init_command();
    println!("{:#?}", command);
    command.exec();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013-2014, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std::vec::Vec;

use capability::{ClientHook, FromClientHook, PipelineHook, PipelineOp};
use layout::{PointerReader, PointerBuilder};
use traits::{FromPointerReader, FromPointerBuilder, SetPointerBuilder};

#[deriving(Copy)]
pub struct Reader<'a> {
    reader : PointerReader<'a>
}

impl <'a> Reader<'a> {
    #[inline]
    pub fn new<'b>(reader : PointerReader<'b>) -> Reader<'b> {
        Reader { reader : reader }
    }

    #[inline]
    pub fn is_null(&self) -> bool {
        self.reader.is_null()
    }

    #[inline]
    pub fn get_as<T : FromPointerReader<'a>>(&self) -> T {
        FromPointerReader::get_from_pointer(&self.reader)
    }

    pub fn get_as_capability<T : FromClientHook>(&self) -> T {
        FromClientHook::new(self.reader.get_capability())
    }

    //# Used by RPC system to implement pipelining. Applications
    //# generally shouldn't use this directly.
    pub fn get_pipelined_cap(&self, ops : &[PipelineOp]) -> Box<ClientHook+Send> {
        let mut pointer = self.reader;

        for op in ops.iter() {
            match op {
                &PipelineOp::Noop =>  { }
                &PipelineOp::GetPointerField(idx) => {
                    pointer = pointer.get_struct(::std::ptr::null()).get_pointer_field(idx as uint)
                }
            }
        }

        pointer.get_capability()
    }
}

pub struct Builder<'a> {
    builder : PointerBuilder<'a>
}

impl <'a> Builder<'a> {
    #[inline]
    pub fn new<'b>(builder : PointerBuilder<'a>) -> Builder<'a> {
        Builder { builder : builder }
    }

    pub fn get_as<T : FromPointerBuilder<'a>>(self) -> T {
        FromPointerBuilder::get_from_pointer(self.builder)
    }

    pub fn init_as<T : FromPointerBuilder<'a>>(self) -> T {
        FromPointerBuilder::init_pointer(self.builder, 0)
    }

    pub fn init_as_sized<T : FromPointerBuilder<'a>>(self, size : u32) -> T {
        FromPointerBuilder::init_pointer(self.builder, size)
    }

    pub fn set_as<To, From : SetPointerBuilder<To>>(self, value : From) {
        SetPointerBuilder::<To>::set_pointer_builder(self.builder, value);
    }

    // XXX value should be a user client.
    pub fn set_as_capability(&self, value : Box<ClientHook+Send>) {
        self.builder.set_capability(value);
    }

    #[inline]
    pub fn clear(&mut self) {
        self.builder.clear()
    }

    #[inline]
    pub fn as_reader<'b>(&'b self) -> Reader<'b> {
        Reader { reader : self.builder.as_reader() }
    }
}

pub struct Pipeline {
    hook : Box<PipelineHook+Send>,
    ops : Vec<PipelineOp>,
}

impl Pipeline {
    pub fn new(hook : Box<PipelineHook+Send>) -> Pipeline {
        Pipeline { hook : hook, ops : Vec::new() }
    }

    pub fn noop(&self) -> Pipeline {
        Pipeline { hook : self.hook.copy(), ops : self.ops.clone() }
    }

    pub fn get_pointer_field(&self, pointer_index : u16) -> Pipeline {
        let mut new_ops = Vec::with_capacity(self.ops.len() + 1);
        for &op in self.ops.iter() {
            new_ops.push(op)
        }
        new_ops.push(PipelineOp::GetPointerField(pointer_index));
        Pipeline { hook : self.hook.copy(), ops : new_ops }
    }

    pub fn as_cap(&self) -> Box<ClientHook+Send> {
        self.hook.get_pipelined_cap(self.ops.clone())
    }
}

<commit_msg>tweak<commit_after>/*
 * Copyright (c) 2013-2014, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std::vec::Vec;

use capability::{ClientHook, FromClientHook, PipelineHook, PipelineOp};
use layout::{PointerReader, PointerBuilder};
use traits::{FromPointerReader, FromPointerBuilder, SetPointerBuilder};

#[deriving(Copy)]
pub struct Reader<'a> {
    reader : PointerReader<'a>
}

impl <'a> Reader<'a> {
    #[inline]
    pub fn new<'b>(reader : PointerReader<'b>) -> Reader<'b> {
        Reader { reader : reader }
    }

    #[inline]
    pub fn is_null(&self) -> bool {
        self.reader.is_null()
    }

    #[inline]
    pub fn get_as<T : FromPointerReader<'a>>(&self) -> T {
        FromPointerReader::get_from_pointer(&self.reader)
    }

    pub fn get_as_capability<T : FromClientHook>(&self) -> T {
        FromClientHook::new(self.reader.get_capability())
    }

    //# Used by RPC system to implement pipelining. Applications
    //# generally shouldn't use this directly.
    pub fn get_pipelined_cap(&self, ops : &[PipelineOp]) -> Box<ClientHook+Send> {
        let mut pointer = self.reader;

        for op in ops.iter() {
            match op {
                &PipelineOp::Noop =>  { }
                &PipelineOp::GetPointerField(idx) => {
                    pointer = pointer.get_struct(::std::ptr::null()).get_pointer_field(idx as uint)
                }
            }
        }

        pointer.get_capability()
    }
}

pub struct Builder<'a> {
    builder : PointerBuilder<'a>
}

impl <'a> Builder<'a> {
    #[inline]
    pub fn new<'b>(builder : PointerBuilder<'a>) -> Builder<'a> {
        Builder { builder : builder }
    }

    pub fn get_as<T : FromPointerBuilder<'a>>(self) -> T {
        FromPointerBuilder::get_from_pointer(self.builder)
    }

    pub fn init_as<T : FromPointerBuilder<'a>>(self) -> T {
        FromPointerBuilder::init_pointer(self.builder, 0)
    }

    pub fn init_as_sized<T : FromPointerBuilder<'a>>(self, size : u32) -> T {
        FromPointerBuilder::init_pointer(self.builder, size)
    }

    pub fn set_as<To, From : SetPointerBuilder<To>>(self, value : From) {
        SetPointerBuilder::<To>::set_pointer_builder(self.builder, value);
    }

    // XXX value should be a user client.
    pub fn set_as_capability(&self, value : Box<ClientHook+Send>) {
        self.builder.set_capability(value);
    }

    #[inline]
    pub fn clear(&mut self) {
        self.builder.clear()
    }

    #[inline]
    pub fn as_reader(self) -> Reader<'a> {
        Reader { reader : self.builder.as_reader() }
    }
}

pub struct Pipeline {
    hook : Box<PipelineHook+Send>,
    ops : Vec<PipelineOp>,
}

impl Pipeline {
    pub fn new(hook : Box<PipelineHook+Send>) -> Pipeline {
        Pipeline { hook : hook, ops : Vec::new() }
    }

    pub fn noop(&self) -> Pipeline {
        Pipeline { hook : self.hook.copy(), ops : self.ops.clone() }
    }

    pub fn get_pointer_field(&self, pointer_index : u16) -> Pipeline {
        let mut new_ops = Vec::with_capacity(self.ops.len() + 1);
        for &op in self.ops.iter() {
            new_ops.push(op)
        }
        new_ops.push(PipelineOp::GetPointerField(pointer_index));
        Pipeline { hook : self.hook.copy(), ops : new_ops }
    }

    pub fn as_cap(&self) -> Box<ClientHook+Send> {
        self.hook.get_pipelined_cap(self.ops.clone())
    }
}

<|endoftext|>


<commit_before><commit_msg>Prettify the upgrade command output<commit_after><|endoftext|>


<commit_before>extern crate compiletest_rs as compiletest;

use std::path::{PathBuf, Path};
use std::io::Write;

fn compile_fail(sysroot: &str) {
    let flags = format!("--sysroot {} -Dwarnings", sysroot);
    for_all_targets(sysroot, |target| {
        let mut config = compiletest::default_config();
        config.host_rustcflags = Some(flags.clone());
        config.mode = "compile-fail".parse().expect("Invalid mode");
        config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
        config.rustc_path = "target/debug/miri".into();
        config.src_base = PathBuf::from("tests/compile-fail".to_string());
        config.target = target.to_owned();
        config.target_rustcflags = Some(flags.clone());
        compiletest::run_tests(&config);
    });
}

fn run_pass() {
    let mut config = compiletest::default_config();
    config.mode = "run-pass".parse().expect("Invalid mode");
    config.src_base = PathBuf::from("tests/run-pass".to_string());
    config.target_rustcflags = Some("-Dwarnings".to_string());
    config.host_rustcflags = Some("-Dwarnings".to_string());
    compiletest::run_tests(&config);
}

fn for_all_targets<F: FnMut(String)>(sysroot: &str, mut f: F) {
    for target in std::fs::read_dir(format!("{}/lib/rustlib/", sysroot)).unwrap() {
        let target = target.unwrap();
        if !target.metadata().unwrap().is_dir() {
            continue;
        }
        let target = target.file_name().into_string().unwrap();
        if target == "etc" {
            continue;
        }
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
        f(target);
    }
}

#[test]
fn compile_test() {
    // Taken from https://github.com/Manishearth/rust-clippy/pull/911.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    let sysroot = match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
            .to_owned(),
    };
    compile_fail(&sysroot);
    run_pass();
    for_all_targets(&sysroot, |target| {
        let files = std::fs::read_dir("tests/run-pass").unwrap();
        let files: Box<Iterator<Item=_>> = if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") {
            Box::new(files.chain(std::fs::read_dir(path).unwrap()))
        } else {
            Box::new(files)
        };
        let mut mir_not_found = 0;
        let mut crate_not_found = 0;
        let mut success = 0;
        let mut failed = 0;
        for file in files {
            let file = file.unwrap();
            let path = file.path();

            if !file.metadata().unwrap().is_file() || !path.to_str().unwrap().ends_with(".rs") {
                continue;
            }

            let stderr = std::io::stderr();
            write!(stderr.lock(), "test [miri-pass] {} ... ", path.display()).unwrap();
            let mut cmd = std::process::Command::new("target/debug/miri");
            cmd.arg(path);
            cmd.arg(format!("--target={}", target));
            let libs = Path::new(&sysroot).join("lib");
            let sysroot = libs.join("rustlib").join(&target).join("lib");
            let paths = std::env::join_paths(&[libs, sysroot]).unwrap();
            cmd.env(compiletest::procsrv::dylib_env_var(), paths);

            match cmd.output() {
                Ok(ref output) if output.status.success() => {
                    success += 1;
                    writeln!(stderr.lock(), "ok").unwrap()
                },
                Ok(output) => {
                    let output_err = std::str::from_utf8(&output.stderr).unwrap();
                    if let Some(text) = output_err.splitn(2, "thread 'main' panicked at 'no mir for `").nth(1) {
                        mir_not_found += 1;
                        let end = text.find('`').unwrap();
                        writeln!(stderr.lock(), "NO MIR FOR `{}`", &text[..end]).unwrap();
                    } else if let Some(text) = output_err.splitn(2, "can't find crate for `").nth(1) {
                        crate_not_found += 1;
                        let end = text.find('`').unwrap();
                        writeln!(stderr.lock(), "CAN'T FIND CRATE FOR `{}`", &text[..end]).unwrap();
                    } else {
                        failed += 1;
                        writeln!(stderr.lock(), "FAILED with exit code {:?}", output.status.code()).unwrap();
                        writeln!(stderr.lock(), "stdout: \n {}", std::str::from_utf8(&output.stdout).unwrap()).unwrap();
                        writeln!(stderr.lock(), "stderr: \n {}", output_err).unwrap();
                    }
                }
                Err(e) => {
                    writeln!(stderr.lock(), "FAILED: {}", e).unwrap();
                    panic!("failed to execute miri");
                },
            }
        }
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "{} success, {} mir not found, {} crate not found, {} failed", success, mir_not_found, crate_not_found, failed).unwrap();
        assert_eq!(failed, 0, "some tests failed");
    });
}
<commit_msg>run compile-fail tests after run-pass tests<commit_after>extern crate compiletest_rs as compiletest;

use std::path::{PathBuf, Path};
use std::io::Write;

fn compile_fail(sysroot: &str) {
    let flags = format!("--sysroot {} -Dwarnings", sysroot);
    for_all_targets(sysroot, |target| {
        let mut config = compiletest::default_config();
        config.host_rustcflags = Some(flags.clone());
        config.mode = "compile-fail".parse().expect("Invalid mode");
        config.run_lib_path = Path::new(sysroot).join("lib").join("rustlib").join(&target).join("lib");
        config.rustc_path = "target/debug/miri".into();
        config.src_base = PathBuf::from("tests/compile-fail".to_string());
        config.target = target.to_owned();
        config.target_rustcflags = Some(flags.clone());
        compiletest::run_tests(&config);
    });
}

fn run_pass() {
    let mut config = compiletest::default_config();
    config.mode = "run-pass".parse().expect("Invalid mode");
    config.src_base = PathBuf::from("tests/run-pass".to_string());
    config.target_rustcflags = Some("-Dwarnings".to_string());
    config.host_rustcflags = Some("-Dwarnings".to_string());
    compiletest::run_tests(&config);
}

fn for_all_targets<F: FnMut(String)>(sysroot: &str, mut f: F) {
    for target in std::fs::read_dir(format!("{}/lib/rustlib/", sysroot)).unwrap() {
        let target = target.unwrap();
        if !target.metadata().unwrap().is_dir() {
            continue;
        }
        let target = target.file_name().into_string().unwrap();
        if target == "etc" {
            continue;
        }
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "running tests for target {}", target).unwrap();
        f(target);
    }
}

#[test]
fn compile_test() {
    // Taken from https://github.com/Manishearth/rust-clippy/pull/911.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    let sysroot = match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => option_env!("RUST_SYSROOT")
            .expect("need to specify RUST_SYSROOT env var or use rustup or multirust")
            .to_owned(),
    };
    run_pass();
    for_all_targets(&sysroot, |target| {
        let files = std::fs::read_dir("tests/run-pass").unwrap();
        let files: Box<Iterator<Item=_>> = if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") {
            Box::new(files.chain(std::fs::read_dir(path).unwrap()))
        } else {
            Box::new(files)
        };
        let mut mir_not_found = 0;
        let mut crate_not_found = 0;
        let mut success = 0;
        let mut failed = 0;
        for file in files {
            let file = file.unwrap();
            let path = file.path();

            if !file.metadata().unwrap().is_file() || !path.to_str().unwrap().ends_with(".rs") {
                continue;
            }

            let stderr = std::io::stderr();
            write!(stderr.lock(), "test [miri-pass] {} ... ", path.display()).unwrap();
            let mut cmd = std::process::Command::new("target/debug/miri");
            cmd.arg(path);
            cmd.arg(format!("--target={}", target));
            let libs = Path::new(&sysroot).join("lib");
            let sysroot = libs.join("rustlib").join(&target).join("lib");
            let paths = std::env::join_paths(&[libs, sysroot]).unwrap();
            cmd.env(compiletest::procsrv::dylib_env_var(), paths);

            match cmd.output() {
                Ok(ref output) if output.status.success() => {
                    success += 1;
                    writeln!(stderr.lock(), "ok").unwrap()
                },
                Ok(output) => {
                    let output_err = std::str::from_utf8(&output.stderr).unwrap();
                    if let Some(text) = output_err.splitn(2, "thread 'main' panicked at 'no mir for `").nth(1) {
                        mir_not_found += 1;
                        let end = text.find('`').unwrap();
                        writeln!(stderr.lock(), "NO MIR FOR `{}`", &text[..end]).unwrap();
                    } else if let Some(text) = output_err.splitn(2, "can't find crate for `").nth(1) {
                        crate_not_found += 1;
                        let end = text.find('`').unwrap();
                        writeln!(stderr.lock(), "CAN'T FIND CRATE FOR `{}`", &text[..end]).unwrap();
                    } else {
                        failed += 1;
                        writeln!(stderr.lock(), "FAILED with exit code {:?}", output.status.code()).unwrap();
                        writeln!(stderr.lock(), "stdout: \n {}", std::str::from_utf8(&output.stdout).unwrap()).unwrap();
                        writeln!(stderr.lock(), "stderr: \n {}", output_err).unwrap();
                    }
                }
                Err(e) => {
                    writeln!(stderr.lock(), "FAILED: {}", e).unwrap();
                    panic!("failed to execute miri");
                },
            }
        }
        let stderr = std::io::stderr();
        writeln!(stderr.lock(), "{} success, {} mir not found, {} crate not found, {} failed", success, mir_not_found, crate_not_found, failed).unwrap();
        assert_eq!(failed, 0, "some tests failed");
    });
    compile_fail(&sysroot);
}
<|endoftext|>


<commit_before><commit_msg>Follow changes in rust-http2<commit_after><|endoftext|>


<commit_before>//! Defines the messages passed between client and server.

use block_position::BlockPosition;
use entity::EntityId;
use lod::LODIndex;
use nalgebra::{Vec2, Vec3, Pnt3};
use nanomsg::{Endpoint, Socket, Protocol};
use process_events::{process_channel, process_socket};
use rustc_serialize::{Encodable, Decodable, json};
use std::fmt::Debug;
use std::old_io::timer;
use std::sync::mpsc::{channel, Sender, Receiver};
use std::time::duration::Duration;
use std::thread::Thread;
use terrain_block::TerrainBlock;
use vertex::ColoredVertex;

#[derive(Debug, Clone)]
#[derive(RustcDecodable, RustcEncodable)]
/// Messages the client sends to the server.
pub enum ClientToServer {
  /// Notify the server that the client exists, and provide a "return address".
  Init(String),
  /// Add a vector the player's acceleration.
  Walk(Vec3<f32>),
  /// Rotate the player by some amount.
  RotatePlayer(Vec2<f32>),
  /// [Try to] start a jump for the player.
  StartJump,
  /// [Try to] stop a jump for the player.
  StopJump,
  /// Ask the server to send a block of terrain.
  RequestBlock(BlockPosition, LODIndex),
}

#[derive(Debug, Clone)]
#[derive(RustcDecodable, RustcEncodable)]
/// Messages the server sends to the client.
pub enum ServerToClient {
  /// Update the player's position.
  UpdatePlayer(Pnt3<f32>),

  /// Tell the client to add a new mob with the given mesh.
  AddMob(EntityId, Vec<ColoredVertex>),
  /// Update the client's view of a mob with a given mesh.
  UpdateMob(EntityId, Vec<ColoredVertex>),

  /// The sun as a [0, 1) portion of its cycle.
  UpdateSun(f32),

  /// Provide a block of terrain to a client.
  AddBlock(BlockPosition, TerrainBlock, LODIndex),
}

/// Spawn a new thread to send messages to a socket and wait for acks.
pub fn spark_socket_sender<T>(url: String) -> (Sender<T>, Endpoint)
  where T: Send + Encodable + Debug
{
  let mut socket = Socket::new(Protocol::Push).unwrap();
  let endpoint = socket.connect(url.as_slice()).unwrap();

  let (send, recv) = channel();

  Thread::spawn(move || {
    loop {
      let mut n = 0;
      process_channel(
        &recv,
        |request| {
          let request = json::encode(&request).unwrap();
          if let Err(e) = socket.write_all(request.as_bytes()) {
            panic!("Error sending message: {:?}", e);
          }
          n += 1;
          true
        }
      );

      timer::sleep(Duration::milliseconds(0));
    }
  });

  (send, endpoint)
}

/// Spawn a new thread to read messages from a socket and ack.
pub fn spark_socket_receiver<T>(url: String) -> (Receiver<T>, Endpoint)
  where T: Send + Decodable
{
  let mut socket = Socket::new(Protocol::Pull).unwrap();
  let endpoint = socket.bind(url.as_slice()).unwrap();

  let (send, recv) = channel();

  Thread::spawn(move || {
    loop {
      process_socket(
        &mut socket,
        |t| {
          send.send(t).unwrap();
          true
        },
      );

      timer::sleep(Duration::milliseconds(0));
    }
  });

  (recv, endpoint)
}
<commit_msg>Less branchy spark_socket_{send,receiv}er.<commit_after>//! Defines the messages passed between client and server.

use block_position::BlockPosition;
use entity::EntityId;
use lod::LODIndex;
use nalgebra::{Vec2, Vec3, Pnt3};
use nanomsg::{Endpoint, Socket, Protocol};
use rustc_serialize::{Encodable, Decodable, json};
use std::fmt::Debug;
use std::old_io::timer;
use std::sync::mpsc::{channel, Sender, Receiver};
use std::time::duration::Duration;
use std::thread::Thread;
use terrain_block::TerrainBlock;
use vertex::ColoredVertex;

#[derive(Debug, Clone)]
#[derive(RustcDecodable, RustcEncodable)]
/// Messages the client sends to the server.
pub enum ClientToServer {
  /// Notify the server that the client exists, and provide a "return address".
  Init(String),
  /// Add a vector the player's acceleration.
  Walk(Vec3<f32>),
  /// Rotate the player by some amount.
  RotatePlayer(Vec2<f32>),
  /// [Try to] start a jump for the player.
  StartJump,
  /// [Try to] stop a jump for the player.
  StopJump,
  /// Ask the server to send a block of terrain.
  RequestBlock(BlockPosition, LODIndex),
}

#[derive(Debug, Clone)]
#[derive(RustcDecodable, RustcEncodable)]
/// Messages the server sends to the client.
pub enum ServerToClient {
  /// Update the player's position.
  UpdatePlayer(Pnt3<f32>),

  /// Tell the client to add a new mob with the given mesh.
  AddMob(EntityId, Vec<ColoredVertex>),
  /// Update the client's view of a mob with a given mesh.
  UpdateMob(EntityId, Vec<ColoredVertex>),

  /// The sun as a [0, 1) portion of its cycle.
  UpdateSun(f32),

  /// Provide a block of terrain to a client.
  AddBlock(BlockPosition, TerrainBlock, LODIndex),
}

/// Spawn a new thread to send messages to a socket and wait for acks.
pub fn spark_socket_sender<T>(url: String) -> (Sender<T>, Endpoint)
  where T: Send + Encodable + Debug
{
  let mut socket = Socket::new(Protocol::Push).unwrap();
  let endpoint = socket.connect(url.as_slice()).unwrap();

  let (send, recv) = channel();

  Thread::spawn(move || {
    loop {
      match recv.recv() {
        Err(e) => panic!("Error receiving from channel: {:?}", e),
        Ok(msg) => {
          let msg = json::encode(&msg).unwrap();
          if let Err(e) = socket.write_all(msg.as_bytes()) {
            panic!("Error sending message: {:?}", e);
          }
        }
      };

      timer::sleep(Duration::milliseconds(0));
    }
  });

  (send, endpoint)
}

/// Spawn a new thread to read messages from a socket and ack.
pub fn spark_socket_receiver<T>(url: String) -> (Receiver<T>, Endpoint)
  where T: Send + Decodable
{
  let mut socket = Socket::new(Protocol::Pull).unwrap();
  let endpoint = socket.bind(url.as_slice()).unwrap();

  let (send, recv) = channel();

  Thread::spawn(move || {
    loop {
      match socket.read_to_end() {
        Err(e) => panic!("Error reading from socket: {:?}", e),
        Ok(s) => {
          let s = String::from_utf8(s).unwrap();
          let msg = json::decode(s.as_slice()).unwrap();
          send.send(msg).unwrap();
        },
      }

      timer::sleep(Duration::milliseconds(0));
    }
  });

  (recv, endpoint)
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate lazy_static;
extern crate futures;
extern crate tokio;
extern crate tokio_io;
extern crate trust_dns_resolver;

use std::io;
use std::net::SocketAddr;

use futures::Future;
use tokio_io::IoFuture;
use trust_dns_resolver::{IntoName, ResolverFuture, TryParseIp};

// This is an example of registering a static global resolver into any system.
//
// We may want to create a GlobalResolver as part of the Resolver library
//   in the mean time, this example has the necessary steps to do so.
//
// Thank you to @zonyitoo for the original example.

lazy_static! {
    // First we need to setup the global Resolver
    static ref GLOBAL_DNS_RESOLVER: ResolverFuture = {
        use std::sync::{Arc, Mutex, Condvar};
        use std::thread;

        // We'll be using this condvar to get the Resolver from the thread...
        let pair = Arc::new((Mutex::new(None::<ResolverFuture>), Condvar::new()));
        let pair2 = pair.clone();

        // Spawn the runtime to a new thread...
        //
        // This thread will manage the actual resolution runtime
        thread::spawn(move || {
            // A runtime for this new thread
            let mut runtime = tokio::runtime::current_thread::Runtime::new().expect("failed to launch Runtime");

            // our platform independent future, result, see next blocks
            let future;

            // To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration:
            #[cfg(any(unix, windows))]
            {
                // use the system resolver configuration
                future = ResolverFuture::from_system_conf().expect("Failed to create ResolverFuture");
            }

            // For other operating systems, we can use one of the preconfigured definitions
            #[cfg(not(any(unix, windows)))]
            {
                // Directly reference the config types
                use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};

                // Get a new resolver with the google nameservers as the upstream recursive resolvers
                future = ResolverFuture::new(ResolverConfig::google(), ResolverOpts::default()).expect("Failed to create ResolverFuture");
            }

            // this will block the thread until the Resolver is constructed with the above configuration
            let resolver = runtime.block_on(future).expect("Failed to create DNS resolver");

            let &(ref lock, ref cvar) = &*pair2;
            let mut started = lock.lock().unwrap();
            *started = Some(resolver);
            cvar.notify_one();
            drop(started);

            runtime.run().expect("Resolver Thread shutdown!");
        });

        // Wait for the thread to start up.
        let &(ref lock, ref cvar) = &*pair;
        let mut resolver = lock.lock().unwrap();
        while resolver.is_none() {
            resolver = cvar.wait(resolver).unwrap();
        }

        // take the started resolver
        let resolver = std::mem::replace(&mut *resolver, None);

        // set the global resolver
        resolver.expect("resolver should not be none")
    };
}

/// Provide a general purpose resolution function.
///
/// This looks up the `host` (a &str or String is good), and combines that with the provided port
///   this mimics the lookup functions of std::net.
pub fn resolve<N: IntoName + TryParseIp>(host: N, port: u16) -> IoFuture<Vec<SocketAddr>> {
    // Now we use the global resolver to perform a lookup_ip.
    let resolve_future = GLOBAL_DNS_RESOLVER.lookup_ip(host).then(move |result| {
        // map the result into what we want...
        result
            .map_err(move |err| {
                // we transform the error into a standard IO error for convenience
                io::Error::new(
                    io::ErrorKind::AddrNotAvailable,
                    format!("dns resolution error: {}", err),
                )
            })
            .map(move |lookup_ip| {
                // we take all the IPs returned, and then send back the set of IPs
                lookup_ip
                    .iter()
                    .map(|ip| SocketAddr::new(ip, port))
                    .collect::<Vec<_>>()
            })
    });

    // Now return the boxed future
    Box::new(resolve_future)
}

fn main() {
    use std::thread;
    use std::time::Duration;

    // Let's resolve some names, we should be able to do it across threads
    let names = &["www.google.com", "www.reddit.com", "www.wikipedia.org"];

    // println!("spawning to runtime");
    // runtime.spawn(
    //     resolve("www.google.com", 443)
    //         .map(|addrs| println!("addrs: {:?}", addrs))
    //         .map_err(|err| println!("lookup error: {}", err)),
    // );

    thread::sleep(Duration::from_secs(1));

    // spawn all the threads to do the lookups
    let threads = names
        .iter()
        .map(|name| {
            let join = thread::spawn(move || {
                let mut runtime = tokio::runtime::current_thread::Runtime::new()
                    .expect("failed to launch Runtime");
                runtime.block_on(resolve(*name, 443))
            });

            (name, join)
        })
        .collect::<Vec<_>>();

    for (name, join) in threads {
        let result = join.join();
        println!("{} resolved to {:?}", name, result);
    }
}
<commit_msg>clean up global example a little<commit_after>#[macro_use]
extern crate lazy_static;
extern crate futures;
extern crate tokio;
extern crate tokio_io;
extern crate trust_dns_resolver;

use std::io;
use std::net::SocketAddr;

use futures::Future;
use tokio_io::IoFuture;
use trust_dns_resolver::{IntoName, ResolverFuture, TryParseIp};

// This is an example of registering a static global resolver into any system.
//
// We may want to create a GlobalResolver as part of the Resolver library
//   in the mean time, this example has the necessary steps to do so.
//
// Thank you to @zonyitoo for the original example.

lazy_static! {
    // First we need to setup the global Resolver
    static ref GLOBAL_DNS_RESOLVER: ResolverFuture = {
        use std::sync::{Arc, Mutex, Condvar};
        use std::thread;

        // We'll be using this condvar to get the Resolver from the thread...
        let pair = Arc::new((Mutex::new(None::<ResolverFuture>), Condvar::new()));
        let pair2 = pair.clone();

        // Spawn the runtime to a new thread...
        //
        // This thread will manage the actual resolution runtime
        thread::spawn(move || {
            // A runtime for this new thread
            let mut runtime = tokio::runtime::current_thread::Runtime::new().expect("failed to launch Runtime");

            // our platform independent future, result, see next blocks
            let future;

            // To make this independent, if targeting macOS, BSD, Linux, or Windows, we can use the system's configuration:
            #[cfg(any(unix, windows))]
            {
                // use the system resolver configuration
                future = ResolverFuture::from_system_conf().expect("Failed to create ResolverFuture");
            }

            // For other operating systems, we can use one of the preconfigured definitions
            #[cfg(not(any(unix, windows)))]
            {
                // Directly reference the config types
                use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};

                // Get a new resolver with the google nameservers as the upstream recursive resolvers
                future = ResolverFuture::new(ResolverConfig::google(), ResolverOpts::default()).expect("Failed to create ResolverFuture");
            }

            // this will block the thread until the Resolver is constructed with the above configuration
            let resolver = runtime.block_on(future).expect("Failed to create DNS resolver");

            let &(ref lock, ref cvar) = &*pair2;
            let mut started = lock.lock().unwrap();
            *started = Some(resolver);
            cvar.notify_one();
            drop(started);

            runtime.run().expect("Resolver Thread shutdown!");
        });

        // Wait for the thread to start up.
        let &(ref lock, ref cvar) = &*pair;
        let mut resolver = lock.lock().unwrap();
        while resolver.is_none() {
            resolver = cvar.wait(resolver).unwrap();
        }

        // take the started resolver
        let resolver = std::mem::replace(&mut *resolver, None);

        // set the global resolver
        resolver.expect("resolver should not be none")
    };
}

/// Provide a general purpose resolution function.
///
/// This looks up the `host` (a &str or String is good), and combines that with the provided port
///   this mimics the lookup functions of std::net.
pub fn resolve<N: IntoName + TryParseIp>(host: N, port: u16) -> IoFuture<Vec<SocketAddr>> {
    // Now we use the global resolver to perform a lookup_ip.
    let resolve_future = GLOBAL_DNS_RESOLVER.lookup_ip(host).then(move |result| {
        // map the result into what we want...
        result
            .map_err(move |err| {
                // we transform the error into a standard IO error for convenience
                io::Error::new(
                    io::ErrorKind::AddrNotAvailable,
                    format!("dns resolution error: {}", err),
                )
            })
            .map(move |lookup_ip| {
                // we take all the IPs returned, and then send back the set of IPs
                lookup_ip
                    .iter()
                    .map(|ip| SocketAddr::new(ip, port))
                    .collect::<Vec<_>>()
            })
    });

    // Now return the boxed future
    Box::new(resolve_future)
}

fn main() {
    use std::thread;

    // Let's resolve some names, we should be able to do it across threads
    let names = &["www.google.com", "www.reddit.com", "www.wikipedia.org"];

    // spawn all the threads to do the lookups
    let threads = names
        .iter()
        .map(|name| {
            let join = thread::spawn(move || {
                let mut runtime = tokio::runtime::current_thread::Runtime::new()
                    .expect("failed to launch Runtime");
                runtime.block_on(resolve(*name, 443))
            });

            (name, join)
        })
        .collect::<Vec<_>>();

    // print the resolved IPs
    for (name, join) in threads {
        let result = join.join();
        println!("{} resolved to {:?}", name, result);
    }
}
<|endoftext|>


<commit_before>#![allow(unstable)]

extern crate test;
extern crate wheel_timer;

use wheel_timer::WheelTimer;

#[test]
fn wheel_timer_schedule_test() {
  let mut timer = WheelTimer::new(10);
  timer.schedule(3, "tick");

  timer.tick();
  timer.tick();
  timer.tick();

  let list = timer.tick();
  assert_eq!(list.len(), 1);

  let val = list[0];
  assert_eq!(val, "tick");
}

#[test]
fn wheel_timer_tick_test() {
  let mut timer = WheelTimer::new(10);

  for i in range(0, 10) {
    timer.schedule(i, i)
  }

  for i in range(0, 10) {
    let list = timer.tick();
    assert_eq!(list.len(), 1);

    let val = list[0];
    assert_eq!(val, i);
  }
}

#[test]
fn wheel_timer_size_test() {
  let mut timer = WheelTimer::new(10);

  for i in range(0, 10) {
    timer.schedule(i, i)
  }

  assert_eq!(timer.size(), 10);

  for _ in timer {
  }

  assert_eq!(timer.size(), 0);
}
<commit_msg>Fixing up tests<commit_after>#![feature(core)]
#![feature(test)]

extern crate test;
extern crate wheel_timer;

use wheel_timer::WheelTimer;

#[test]
fn wheel_timer_schedule_test() {
  let mut timer = WheelTimer::new(10);
  timer.schedule(3, "tick");

  timer.tick();
  timer.tick();
  timer.tick();

  let list = timer.tick();
  assert_eq!(list.len(), 1);

  let val = list[0];
  assert_eq!(val, "tick");
}

#[test]
fn wheel_timer_tick_test() {
  let mut timer = WheelTimer::new(10);

  for i in range(0, 10) {
    timer.schedule(i, i)
  }

  for i in range(0, 10) {
    let list = timer.tick();
    assert_eq!(list.len(), 1);

    let val = list[0];
    assert_eq!(val, i);
  }
}

#[test]
fn wheel_timer_size_test() {
  let mut timer = Box::new(WheelTimer::new(10));

  for i in range(0, 10) {
    timer.schedule(i, i)
  }

  assert_eq!(timer.size(), 10);

  for _ in range(0, 10) {
    timer.tick();
  }

  assert_eq!(timer.size(), 0);
}
<|endoftext|>


<commit_before>
// Copyright 2017 The gltf Library Developers
//
// 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.
use byteorder::{LE, ReadBytesExt};

use std::{fmt, io};

/// Represents a Glb loader error.
#[derive(Debug)]
pub enum Error {
    /// Io error occured.
    Io(::std::io::Error),
    /// Unsupported version.
    Version(u32),
    /// Magic says that file is not glTF.
    Magic([u8; 4]),
    /// Length specified in GLB header exceeeds that of slice.
    Length {
        /// length specified in GLB header.
        length: u32,
        /// Actual length of data read.
        length_read: usize,
    },
    /// Stream ended before we could read the chunk.
    ChunkLength {
        /// chunkType error happened at.
        ty: ChunkType,
        /// chunkLength.
        length: u32,
        /// Actual length of data read.
        length_read: usize,
    },
    /// Chunk of this chunkType was not expected.
    ChunkType(ChunkType),
    /// Unknown chunk type.
    UnknownChunkType([u8; 4]),
}

/// The contents of a .glb file.
#[derive(Clone, Debug)]
pub struct Glb<'a> {
    /// The header section of the `.glb` file.
    pub header: Header,
    /// The JSON section of the `.glb` file.
    pub json: &'a [u8],
    /// The optional BIN section of the `.glb` file.
    pub bin: Option<&'a [u8]>,
}

/// The header section of a .glb file.
#[derive(Copy, Clone, Debug)]
pub struct Header {
    /// Must be `b"glTF"`.
    pub magic: [u8; 4],
    /// Must be `2`.
    pub version: u32,
    /// Must match the length of the parent .glb file.
    pub length: u32,
}

/// GLB chunk type.
#[derive(Copy, Clone, Debug)]
pub enum ChunkType {
    /// JSON chunk.
    Json,
    /// BIN\0 chunk.
    Bin,
}

/// Chunk header with no data read yet.
#[derive(Copy, Clone, Debug)]
struct ChunkHeader {
    /// The length of the chunk data in byte excluding the header.
    length: u32,
    /// Chunk type.
    ty: ChunkType,
}

impl Header {
    fn from_reader<R: io::Read>(mut reader: R) -> Result<Self, Error> {
        use self::Error::Io;
        let mut magic = [0; 4];
        reader.read_exact(&mut magic).map_err(Io)?;
        // We only validate magic as we don't care for version and length of
        // contents, the caller does.  Let them decide what to do next with
        // regard to version and length.
        if &magic == b"glTF" {
            Ok(Self {
                magic,
                version: reader.read_u32::<LE>().map_err(Io)?,
                length: reader.read_u32::<LE>().map_err(Io)?,
            })
        } else {
            Err(Error::Magic(magic))
        }
    }

    fn size_of() -> usize { 12 }
}

impl ChunkHeader {
    fn from_reader<R: io::Read>(mut reader: R) -> Result<Self, Error> {
        use self::Error::Io;
        let length = reader.read_u32::<LE>().map_err(Io)?;
        let mut ty = [0; 4];
        reader.read_exact(&mut ty).map_err(Io)?;
        let ty = match &ty {
            b"JSON" => Ok(ChunkType::Json),
            b"BIN\0" => Ok(ChunkType::Bin),
            _ => Err(Error::UnknownChunkType(ty)),
        }?;
        Ok(Self { length, ty })
    }
}

impl<'a> Glb<'a> {
    /// Splits loaded GLB into its three chunks.
    ///
    /// * Mandatory GLB header.
    /// * Mandatory JSON chunk.
    /// * Optional BIN chunk.
    pub fn from_slice(mut data: &'a [u8]) -> Result<Self, ::Error> {
        let header = Header::from_reader(&mut data)
            .and_then(|header| {
                let contents_length = header.length as usize - Header::size_of();
                if contents_length <= data.len() {
                    Ok(header)
                } else {
                    Err(Error::Length {
                        length: contents_length as u32,
                        length_read: data.len(),
                    })
                }
            })
            .map_err(::Error::Glb)?;
        match header.version {
            2 => Self::from_v2(data)
                .map(|(json, bin)| Glb { header, json, bin })
                .map_err(::Error::Glb),
            x => Err(::Error::Glb(Error::Version(x)))
        }
    }

    /// Does the loading job for you.  Provided buf will be cleared before new
    /// data will be written.  When error happens, if only header was read, buf
    /// will not be mutated, otherwise, buf will be empty.
    pub fn from_reader<R: io::Read>(mut reader: R, buf: &'a mut Vec<u8>)
                                    -> Result<Self, ::Error> {
        let header = Header::from_reader(&mut reader).map_err(::Error::Glb)?;
        match header.version {
            2 => {
                let glb_len = header.length - Header::size_of() as u32;
                buf.clear();
                buf.reserve(glb_len as usize);
                // SAFETY: We are doing unsafe operation on a user-supplied
                // container!  Make sure not to expose user to uninitialized
                // data if an error happens during reading.
                //
                // It is guaranteed by reserve's implementation that the reserve
                // call will make buf's capacity _at least_ buf_len.
                //
                // We do not read contents of the Vec unless it is fully
                // initialized.
                unsafe { buf.set_len(glb_len as usize) };
                if let Err(e) = reader.read_exact(buf).map_err(Error::Io) {
                    // SAFETY: It is safe to not run destructors because u8 has
                    // none.
                    unsafe { buf.set_len(0) };
                    Err(::Error::Glb(e))
                } else {
                    Self::from_v2(buf)
                       .map(|(json, bin)| Glb { header, json, bin })
                       .map_err(::Error::Glb)
                }
            }
            x => Err(::Error::Glb(Error::Version(x)))
        }
    }

    fn from_v2(mut data: &'a [u8]) -> Result<(&'a [u8], Option<&'a [u8]>), Error> {
        let (json, mut data) = ChunkHeader::from_reader(&mut data)
            .and_then(|json_h| if let ChunkType::Json = json_h.ty {
                Ok(json_h)
            } else {
                Err(Error::ChunkType(json_h.ty))
            })
            .and_then(|json_h| if json_h.length as usize <= data.len() {
                Ok(json_h)
            } else {
                Err(Error::ChunkLength {
                    ty: json_h.ty,
                    length: json_h.length,
                    length_read: data.len(),
                })
            })
            // PANIC: We have verified that json_h.length is no greater than
            // that of data.len().
            .map(|json_h| data.split_at(json_h.length as usize))?;

        let bin = if data.len() > 0 {
            ChunkHeader::from_reader(&mut data)
                .and_then(|bin_h| if let ChunkType::Bin = bin_h.ty {
                    Ok(bin_h)
                } else {
                    Err(Error::ChunkType(bin_h.ty))
                })
                .and_then(|bin_h| if bin_h.length as usize <= data.len() {
                    Ok(bin_h)
                } else {
                    Err(Error::ChunkLength {
                        ty: bin_h.ty,
                        length: bin_h.length,
                        length_read: data.len(),
                    })
                })
                // PANIC: we have verified that bin_h.length is no greater than
                // that of data.len().
                .map(|bin_h| data.split_at(bin_h.length as usize))
                .map(|(x, _)| Some(x))?
        } else {
            None
        };
        Ok((json, bin))
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;
        write!(f, "{}", self.description())
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
         match *self {
             Error::Io(ref e) => e.description(),
             Error::Version(_) => "unsupported version",
             Error::Magic(_) => "not glTF magic",
             Error::Length { .. } => "could not completely read the object",
             Error::ChunkLength { ty, .. } => match ty {
                 ChunkType::Json => "JSON chunk length exceeds that of slice",
                 ChunkType::Bin => "BIN\\0 chunk length exceeds that of slice",
             },
             Error::ChunkType(ty) => match ty {
                 ChunkType::Json => "was not expecting JSON chunk",
                 ChunkType::Bin => "was not expecting BIN\\0 chunk",
             },
             Error::UnknownChunkType(_) => "unknown chunk type",
        }
    }
}
<commit_msg>Remove redundant and confusing `PANIC's in panic-safety explanation comments<commit_after>
// Copyright 2017 The gltf Library Developers
//
// 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.
use byteorder::{LE, ReadBytesExt};

use std::{fmt, io};

/// Represents a Glb loader error.
#[derive(Debug)]
pub enum Error {
    /// Io error occured.
    Io(::std::io::Error),
    /// Unsupported version.
    Version(u32),
    /// Magic says that file is not glTF.
    Magic([u8; 4]),
    /// Length specified in GLB header exceeeds that of slice.
    Length {
        /// length specified in GLB header.
        length: u32,
        /// Actual length of data read.
        length_read: usize,
    },
    /// Stream ended before we could read the chunk.
    ChunkLength {
        /// chunkType error happened at.
        ty: ChunkType,
        /// chunkLength.
        length: u32,
        /// Actual length of data read.
        length_read: usize,
    },
    /// Chunk of this chunkType was not expected.
    ChunkType(ChunkType),
    /// Unknown chunk type.
    UnknownChunkType([u8; 4]),
}

/// The contents of a .glb file.
#[derive(Clone, Debug)]
pub struct Glb<'a> {
    /// The header section of the `.glb` file.
    pub header: Header,
    /// The JSON section of the `.glb` file.
    pub json: &'a [u8],
    /// The optional BIN section of the `.glb` file.
    pub bin: Option<&'a [u8]>,
}

/// The header section of a .glb file.
#[derive(Copy, Clone, Debug)]
pub struct Header {
    /// Must be `b"glTF"`.
    pub magic: [u8; 4],
    /// Must be `2`.
    pub version: u32,
    /// Must match the length of the parent .glb file.
    pub length: u32,
}

/// GLB chunk type.
#[derive(Copy, Clone, Debug)]
pub enum ChunkType {
    /// JSON chunk.
    Json,
    /// BIN\0 chunk.
    Bin,
}

/// Chunk header with no data read yet.
#[derive(Copy, Clone, Debug)]
struct ChunkHeader {
    /// The length of the chunk data in byte excluding the header.
    length: u32,
    /// Chunk type.
    ty: ChunkType,
}

impl Header {
    fn from_reader<R: io::Read>(mut reader: R) -> Result<Self, Error> {
        use self::Error::Io;
        let mut magic = [0; 4];
        reader.read_exact(&mut magic).map_err(Io)?;
        // We only validate magic as we don't care for version and length of
        // contents, the caller does.  Let them decide what to do next with
        // regard to version and length.
        if &magic == b"glTF" {
            Ok(Self {
                magic,
                version: reader.read_u32::<LE>().map_err(Io)?,
                length: reader.read_u32::<LE>().map_err(Io)?,
            })
        } else {
            Err(Error::Magic(magic))
        }
    }

    fn size_of() -> usize { 12 }
}

impl ChunkHeader {
    fn from_reader<R: io::Read>(mut reader: R) -> Result<Self, Error> {
        use self::Error::Io;
        let length = reader.read_u32::<LE>().map_err(Io)?;
        let mut ty = [0; 4];
        reader.read_exact(&mut ty).map_err(Io)?;
        let ty = match &ty {
            b"JSON" => Ok(ChunkType::Json),
            b"BIN\0" => Ok(ChunkType::Bin),
            _ => Err(Error::UnknownChunkType(ty)),
        }?;
        Ok(Self { length, ty })
    }
}

impl<'a> Glb<'a> {
    /// Splits loaded GLB into its three chunks.
    ///
    /// * Mandatory GLB header.
    /// * Mandatory JSON chunk.
    /// * Optional BIN chunk.
    pub fn from_slice(mut data: &'a [u8]) -> Result<Self, ::Error> {
        let header = Header::from_reader(&mut data)
            .and_then(|header| {
                let contents_length = header.length as usize - Header::size_of();
                if contents_length <= data.len() {
                    Ok(header)
                } else {
                    Err(Error::Length {
                        length: contents_length as u32,
                        length_read: data.len(),
                    })
                }
            })
            .map_err(::Error::Glb)?;
        match header.version {
            2 => Self::from_v2(data)
                .map(|(json, bin)| Glb { header, json, bin })
                .map_err(::Error::Glb),
            x => Err(::Error::Glb(Error::Version(x)))
        }
    }

    /// Does the loading job for you.  Provided buf will be cleared before new
    /// data will be written.  When error happens, if only header was read, buf
    /// will not be mutated, otherwise, buf will be empty.
    pub fn from_reader<R: io::Read>(mut reader: R, buf: &'a mut Vec<u8>)
                                    -> Result<Self, ::Error> {
        let header = Header::from_reader(&mut reader).map_err(::Error::Glb)?;
        match header.version {
            2 => {
                let glb_len = header.length - Header::size_of() as u32;
                buf.clear();
                buf.reserve(glb_len as usize);
                // SAFETY: We are doing unsafe operation on a user-supplied
                // container!  Make sure not to expose user to uninitialized
                // data if an error happens during reading.
                //
                // It is guaranteed by reserve's implementation that the reserve
                // call will make buf's capacity _at least_ buf_len.
                //
                // We do not read contents of the Vec unless it is fully
                // initialized.
                unsafe { buf.set_len(glb_len as usize) };
                if let Err(e) = reader.read_exact(buf).map_err(Error::Io) {
                    // SAFETY: It is safe to not run destructors because u8 has
                    // none.
                    unsafe { buf.set_len(0) };
                    Err(::Error::Glb(e))
                } else {
                    Self::from_v2(buf)
                       .map(|(json, bin)| Glb { header, json, bin })
                       .map_err(::Error::Glb)
                }
            }
            x => Err(::Error::Glb(Error::Version(x)))
        }
    }

    fn from_v2(mut data: &'a [u8]) -> Result<(&'a [u8], Option<&'a [u8]>), Error> {
        let (json, mut data) = ChunkHeader::from_reader(&mut data)
            .and_then(|json_h| if let ChunkType::Json = json_h.ty {
                Ok(json_h)
            } else {
                Err(Error::ChunkType(json_h.ty))
            })
            .and_then(|json_h| if json_h.length as usize <= data.len() {
                Ok(json_h)
            } else {
                Err(Error::ChunkLength {
                    ty: json_h.ty,
                    length: json_h.length,
                    length_read: data.len(),
                })
            })
            // We have verified that json_h.length is no greater than that of
            // data.len().
            .map(|json_h| data.split_at(json_h.length as usize))?;

        let bin = if data.len() > 0 {
            ChunkHeader::from_reader(&mut data)
                .and_then(|bin_h| if let ChunkType::Bin = bin_h.ty {
                    Ok(bin_h)
                } else {
                    Err(Error::ChunkType(bin_h.ty))
                })
                .and_then(|bin_h| if bin_h.length as usize <= data.len() {
                    Ok(bin_h)
                } else {
                    Err(Error::ChunkLength {
                        ty: bin_h.ty,
                        length: bin_h.length,
                        length_read: data.len(),
                    })
                })
                // We have verified that bin_h.length is no greater than that
                // of data.len().
                .map(|bin_h| data.split_at(bin_h.length as usize))
                .map(|(x, _)| Some(x))?
        } else {
            None
        };
        Ok((json, bin))
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use std::error::Error;
        write!(f, "{}", self.description())
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
         match *self {
             Error::Io(ref e) => e.description(),
             Error::Version(_) => "unsupported version",
             Error::Magic(_) => "not glTF magic",
             Error::Length { .. } => "could not completely read the object",
             Error::ChunkLength { ty, .. } => match ty {
                 ChunkType::Json => "JSON chunk length exceeds that of slice",
                 ChunkType::Bin => "BIN\\0 chunk length exceeds that of slice",
             },
             Error::ChunkType(ty) => match ty {
                 ChunkType::Json => "was not expecting JSON chunk",
                 ChunkType::Bin => "was not expecting BIN\\0 chunk",
             },
             Error::UnknownChunkType(_) => "unknown chunk type",
        }
    }
}
<|endoftext|>