<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_gas::{AbstractValueSizeGasParameters, NativeGasParameters, LATEST_GAS_FEATURE_VERSION};
use aptos_types::account_address::{create_resource_address, AccountAddress};
use aptos_vm::natives;
use move_cli::base::test::run_move_unit_tests;
use move_unit_test::UnitTestingConfig;
use move_vm_runtime::native_functions::NativeFunctionTable;
use std::{collections::BTreeMap, path::PathBuf};
use tempfile::tempdir;

pub fn path_in_crate<S>(relative: S) -> PathBuf
where
    S: Into<String>,
{
    let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    path.push(relative.into());
    path
}

pub fn run_tests_for_pkg(
    path_to_pkg: impl Into<String>,
    named_addr: BTreeMap<String, AccountAddress>,
) {
    let pkg_path = path_in_crate(path_to_pkg);
    run_move_unit_tests(
        &pkg_path,
        move_package::BuildConfig {
            test_mode: true,
            install_dir: Some(tempdir().unwrap().path().to_path_buf()),
            additional_named_addresses: named_addr,
            ..Default::default()
        },
        UnitTestingConfig::default_with_bound(Some(100_000)),
        // TODO(Gas): we may want to switch to non-zero costs in the future
        aptos_test_natives(),
        /* cost_table */ None,
        /* compute_coverage */ false,
        &mut std::io::stdout(),
    )
    .unwrap();
}

pub fn aptos_test_natives() -> NativeFunctionTable {
    natives::configure_for_unit_test();
    natives::aptos_natives(
        NativeGasParameters::zeros(),
        AbstractValueSizeGasParameters::zeros(),
        LATEST_GAS_FEATURE_VERSION,
    )
}

#[test]
fn test_data_structures() {
    let named_address = BTreeMap::from([(
        String::from("data_structures"),
        AccountAddress::from_hex_literal("0x1").unwrap(),
    )]);
    run_tests_for_pkg("data_structures", named_address);
}

#[test]
fn test_hello_blockchain() {
    let named_address = BTreeMap::from([(
        String::from("hello_blockchain"),
        AccountAddress::from_hex_literal("0x1").unwrap(),
    )]);
    run_tests_for_pkg("hello_blockchain", named_address);
}

#[test]
fn test_message_board() {
    let named_address = BTreeMap::from([(
        String::from("message_board"),
        AccountAddress::from_hex_literal("0x1").unwrap(),
    )]);
    run_tests_for_pkg("message_board", named_address);
}

#[test]
fn test_minter() {
    let named_address = BTreeMap::new();
    run_tests_for_pkg("scripts/minter", named_address);
}

#[test]
fn test_two_by_two_transfer() {
    let named_address = BTreeMap::new();
    run_tests_for_pkg("scripts/two_by_two_transfer", named_address);
}

#[test]
fn test_shared_account() {
    let named_address = BTreeMap::from([(
        String::from("shared_account"),
        AccountAddress::from_hex_literal("0x1").unwrap(),
    )]);
    run_tests_for_pkg("shared_account", named_address);
}

#[test]
fn test_mint_nft() {
    let named_address = BTreeMap::from([(
        String::from("mint_nft"),
        create_resource_address(
            AccountAddress::from_hex_literal("0xcafe").unwrap(),
            vec![].as_slice(),
        ),
    )]);
    run_tests_for_pkg("mint_nft", named_address);
}

#[test]
fn test_nft_auction_house() {
    let named_address = BTreeMap::from([(
        String::from("marketplace"),
        AccountAddress::from_hex_literal("0xAF").unwrap(),
    )]);
    run_tests_for_pkg("marketplace", named_address);
}

#[test]
fn test_resource_account() {
    let named_address = BTreeMap::from([(
        String::from("resource_account"),
        create_resource_address(
            AccountAddress::from_hex_literal("0xcafe").unwrap(),
            vec![].as_slice(),
        ),
    )]);
    run_tests_for_pkg("resource_account", named_address);
}
<commit_msg>[move-examples] Actually fail tests when test fail<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_gas::{AbstractValueSizeGasParameters, NativeGasParameters, LATEST_GAS_FEATURE_VERSION};
use aptos_types::account_address::{create_resource_address, AccountAddress};
use aptos_vm::natives;
use move_cli::base::test::{run_move_unit_tests, UnitTestResult};
use move_unit_test::UnitTestingConfig;
use move_vm_runtime::native_functions::NativeFunctionTable;
use std::{collections::BTreeMap, path::PathBuf};
use tempfile::tempdir;

pub fn path_in_crate<S>(relative: S) -> PathBuf
where
    S: Into<String>,
{
    let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    path.push(relative.into());
    path
}

pub fn run_tests_for_pkg(
    path_to_pkg: impl Into<String>,
    named_addr: BTreeMap<String, AccountAddress>,
) {
    let pkg_path = path_in_crate(path_to_pkg);
    let ok = run_move_unit_tests(
        &pkg_path,
        move_package::BuildConfig {
            test_mode: true,
            install_dir: Some(tempdir().unwrap().path().to_path_buf()),
            additional_named_addresses: named_addr,
            ..Default::default()
        },
        UnitTestingConfig::default_with_bound(Some(100_000)),
        // TODO(Gas): we may want to switch to non-zero costs in the future
        aptos_test_natives(),
        /* cost_table */ None,
        /* compute_coverage */ false,
        &mut std::io::stdout(),
    )
    .unwrap();
    if ok != UnitTestResult::Success {
        panic!("move unit tests failed")
    }
}

pub fn aptos_test_natives() -> NativeFunctionTable {
    natives::configure_for_unit_test();
    natives::aptos_natives(
        NativeGasParameters::zeros(),
        AbstractValueSizeGasParameters::zeros(),
        LATEST_GAS_FEATURE_VERSION,
    )
}

#[test]
fn test_data_structures() {
    let named_address = BTreeMap::from([(
        String::from("data_structures"),
        AccountAddress::from_hex_literal("0x1").unwrap(),
    )]);
    run_tests_for_pkg("data_structures", named_address);
}

#[test]
fn test_hello_blockchain() {
    let named_address = BTreeMap::from([(
        String::from("hello_blockchain"),
        AccountAddress::from_hex_literal("0x1").unwrap(),
    )]);
    run_tests_for_pkg("hello_blockchain", named_address);
}

#[test]
fn test_message_board() {
    let named_address = BTreeMap::from([(
        String::from("message_board"),
        AccountAddress::from_hex_literal("0x1").unwrap(),
    )]);
    run_tests_for_pkg("message_board", named_address);
}

#[test]
fn test_minter() {
    let named_address = BTreeMap::new();
    run_tests_for_pkg("scripts/minter", named_address);
}

#[test]
fn test_two_by_two_transfer() {
    let named_address = BTreeMap::new();
    run_tests_for_pkg("scripts/two_by_two_transfer", named_address);
}

#[test]
fn test_shared_account() {
    let named_address = BTreeMap::from([(
        String::from("shared_account"),
        AccountAddress::from_hex_literal("0x1").unwrap(),
    )]);
    run_tests_for_pkg("shared_account", named_address);
}

#[test]
fn test_mint_nft() {
    let named_address = BTreeMap::from([(
        String::from("mint_nft"),
        create_resource_address(
            AccountAddress::from_hex_literal("0xcafe").unwrap(),
            vec![].as_slice(),
        ),
    )]);
    run_tests_for_pkg("mint_nft", named_address);
}

#[test]
fn test_nft_auction_house() {
    let named_address = BTreeMap::from([(
        String::from("marketplace"),
        AccountAddress::from_hex_literal("0xAF").unwrap(),
    )]);
    run_tests_for_pkg("marketplace", named_address);
}

#[test]
fn test_resource_account() {
    let named_address = BTreeMap::from([(
        String::from("resource_account"),
        create_resource_address(
            AccountAddress::from_hex_literal("0xcafe").unwrap(),
            vec![].as_slice(),
        ),
    )]);
    run_tests_for_pkg("resource_account", named_address);
}
<|endoftext|>


<commit_before>//! Implements static board evaluation (not implemented yet).

use std::hash::{Hasher, SipHasher};
use basetypes::*;
use moves::*;
use uci::{OptionName, OptionDescription};
use position::bitsets::*;
use position::move_generation::Board;

/// A trait for announcing configuration options, and changing
/// configuration parameters.
pub trait SetOption {
    /// Returns all supported configuration options.
    fn options() -> Vec<(OptionName, OptionDescription)> {
        vec![]
    }

    /// Sets a new value for a given configuration parameter.
    #[allow(unused_variables)]
    fn set_option(&mut self, name: &str, value: &str) {}
}

/// A trait used to statically evaluate the current board.
///
/// The static evaluation of the current board will consider only the
/// static material and positional properties of the position on the
/// board. If the position is dynamic, with pending tactical threats,
/// the static evaluation will return a grossly incorrect
/// evaluation. Therefore, it should be relied upon only for
/// reasonably "quiet" positions.
pub trait BoardEvaluator: Clone + Send + SetOption {
    /// Creates a new instance and binds it to a given position on the
    /// board.
    fn new(board: &Board) -> Self;

    /// Updates evaluator's internal state in accordance with a move
    /// that will be played.
    ///
    /// This method updates the internally maintained properties of
    /// the current position, so that the next call to `evaluate` can
    /// calculate the correct evaluation as quick as possible.
    ///
    /// **Important note:** `m` must be a legal move. `board` must
    /// point to a board that represents exactly the same position as
    /// the one to which the evaluator's instance is bound
    /// to. `will_do_move` must be called before the move `m` is
    /// actually played, and after that, the move must actually be
    /// played.
    #[allow(unused_variables)]
    fn will_do_move(&mut self, board: &Board, m: Move) {}

    /// Updates evaluator's internal state in accordance with a move
    /// that will be taken back.
    ///
    /// This method updates the internally maintained properties of
    /// the current position, so that the next call to `evaluate` can
    /// calculate the correct evaluation as quick as possible.
    ///
    /// **Important note:** `m` must be a legal move. `board` must
    /// point to a board that represents exactly the same position as
    /// the one to which the evaluator's instance is bound
    /// to. `will_undo_move` must be called before the move `m` is
    /// actually taken back, and after that, the move must actually be
    /// taken back.
    #[allow(unused_variables)]
    fn will_undo_move(&mut self, board: &Board, m: Move) {}

    /// Statically evaluates the board.
    ///
    /// The returned value will be between `VALUE_EVAL_MIN` and
    /// `VALUE_EVAL_MAX`.
    ///
    /// **Important note:** `board` must point to a board that
    /// represents exactly the same position as the one to which the
    /// evaluator's instance is bound to.
    fn evaluate(&self, board: &Board) -> Value;
}

#[derive(Clone)]
pub struct RandomEvaluator;

impl SetOption for RandomEvaluator {}

impl BoardEvaluator for RandomEvaluator {
    #[allow(unused_variables)]
    fn new(board: &Board) -> RandomEvaluator {
        RandomEvaluator
    }

    fn evaluate(&self, board: &Board) -> Value {
        const PIECE_VALUES: [Value; 8] = [10000, 975, 500, 325, 325, 100, 0, 0];
        let piece_type = board.pieces().piece_type;
        let color = board.pieces().color;
        let us = board.to_move();
        let them = 1 ^ us;
        let mut result = 0;
        for piece in QUEEN..NO_PIECE {
            result += PIECE_VALUES[piece] *
                      (pop_count(piece_type[piece] & color[us]) as i16 -
                       pop_count(piece_type[piece] & color[them]) as i16);
        }
        let mut hasher = SipHasher::new();
        hasher.write_u64(board.occupied());
        result + (hasher.finish() >> 59) as i16
    }
}

/// Statically evaluates the board.
///
/// This method considers only static material and positional
/// properties of the position. If the position is dynamic, with
/// pending tactical threats, this function will return a grossly
/// incorrect evaluation. Therefore, it should be relied upon only
/// for reasonably "quiet" positions.
///
/// The returned value will always be between `VALUE_EVAL_MIN` and
/// `VALUE_EVAL_MAX`.
#[inline]
pub fn evaluate_board(board: &Board) -> Value {
    // TODO: Implement a real evaluation.

    const PIECE_VALUES: [Value; 8] = [10000, 975, 500, 325, 325, 100, 0, 0];

    if board.checkers() != 0 {
        // In positions under check we can be vastly incorrect with no
        // negative consequences.
        return 0;
    }

    let piece_type = board.pieces().piece_type;
    let color = board.pieces().color;
    let us = board.to_move();
    let them = 1 ^ us;
    let mut result = 0;
    for piece in QUEEN..NO_PIECE {
        result += PIECE_VALUES[piece] *
                  (pop_count(piece_type[piece] & color[us]) as i16 -
                   pop_count(piece_type[piece] & color[them]) as i16);
    }
    let mut hasher = SipHasher::new();
    hasher.write_u64(board.occupied());
    result + (hasher.finish() >> 59) as i16
}

// use rand;
// use rand::distributions::{Sample, Range};
// let mut rng = rand::thread_rng();
// let mut between = Range::new(0, 10);
// let x = between.sample(&mut rng);
<commit_msg>fix docs<commit_after>//! Implements static board evaluation (not implemented yet).

use std::hash::{Hasher, SipHasher};
use basetypes::*;
use moves::*;
use uci::{OptionName, OptionDescription};
use position::bitsets::*;
use position::move_generation::Board;

/// A trait for announcing configuration options, and changing
/// configuration parameters.
pub trait SetOption {
    /// Returns all supported configuration options.
    fn options() -> Vec<(OptionName, OptionDescription)> {
        vec![]
    }

    /// Sets a new value for a given configuration parameter.
    #[allow(unused_variables)]
    fn set_option(&mut self, name: &str, value: &str) {}
}

/// A trait used to statically evaluate the current board.
///
/// The static evaluation of the current board will consider only the
/// static material and positional properties of the position on the
/// board. If the position is dynamic, with pending tactical threats,
/// the static evaluation will return a grossly incorrect
/// evaluation. Therefore, it should be relied upon only for
/// reasonably "quiet" positions.
pub trait BoardEvaluator: Clone + Send + SetOption {
    /// Creates a new instance and binds it to a given position on the
    /// board.
    fn new(board: &Board) -> Self;

    /// Updates evaluator's internal state in accordance with a move
    /// that will be played.
    ///
    /// This method updates the internally maintained properties of
    /// the current position, so that the next call to `evaluate` can
    /// calculate the correct evaluation as quick as possible.
    ///
    /// **Important note:** `m` must be a legal move. `board` must
    /// point to a board that represents exactly the same position as
    /// the one to which the evaluator's instance is bound
    /// to. `will_do_move` must be called before the move `m` is
    /// actually played, and after that, the move must actually be
    /// played.
    #[allow(unused_variables)]
    fn will_do_move(&mut self, board: &Board, m: Move) {}

    /// Updates evaluator's internal state in accordance with a move
    /// that will be taken back.
    ///
    /// This method updates the internally maintained properties of
    /// the current position, so that the next call to `evaluate` can
    /// calculate the correct evaluation as quick as possible.
    ///
    /// **Important note:** `m` must the last played move. `board`
    /// must point to a board that represents exactly the same
    /// position as the one to which the evaluator's instance is bound
    /// to. `will_undo_move` must be called before the move `m` is
    /// actually taken back, and after that, the move must actually be
    /// taken back.
    #[allow(unused_variables)]
    fn will_undo_move(&mut self, board: &Board, m: Move) {}

    /// Statically evaluates the board.
    ///
    /// The returned value will be between `VALUE_EVAL_MIN` and
    /// `VALUE_EVAL_MAX`.
    ///
    /// **Important note:** `board` must point to a board that
    /// represents exactly the same position as the one to which the
    /// evaluator's instance is bound to.
    fn evaluate(&self, board: &Board) -> Value;
}

#[derive(Clone)]
pub struct RandomEvaluator;

impl SetOption for RandomEvaluator {}

impl BoardEvaluator for RandomEvaluator {
    #[allow(unused_variables)]
    fn new(board: &Board) -> RandomEvaluator {
        RandomEvaluator
    }

    fn evaluate(&self, board: &Board) -> Value {
        const PIECE_VALUES: [Value; 8] = [10000, 975, 500, 325, 325, 100, 0, 0];
        let piece_type = board.pieces().piece_type;
        let color = board.pieces().color;
        let us = board.to_move();
        let them = 1 ^ us;
        let mut result = 0;
        for piece in QUEEN..NO_PIECE {
            result += PIECE_VALUES[piece] *
                      (pop_count(piece_type[piece] & color[us]) as i16 -
                       pop_count(piece_type[piece] & color[them]) as i16);
        }
        let mut hasher = SipHasher::new();
        hasher.write_u64(board.occupied());
        result + (hasher.finish() >> 59) as i16
    }
}

/// Statically evaluates the board.
///
/// This method considers only static material and positional
/// properties of the position. If the position is dynamic, with
/// pending tactical threats, this function will return a grossly
/// incorrect evaluation. Therefore, it should be relied upon only
/// for reasonably "quiet" positions.
///
/// The returned value will always be between `VALUE_EVAL_MIN` and
/// `VALUE_EVAL_MAX`.
#[inline]
pub fn evaluate_board(board: &Board) -> Value {
    // TODO: Implement a real evaluation.

    const PIECE_VALUES: [Value; 8] = [10000, 975, 500, 325, 325, 100, 0, 0];

    if board.checkers() != 0 {
        // In positions under check we can be vastly incorrect with no
        // negative consequences.
        return 0;
    }

    let piece_type = board.pieces().piece_type;
    let color = board.pieces().color;
    let us = board.to_move();
    let them = 1 ^ us;
    let mut result = 0;
    for piece in QUEEN..NO_PIECE {
        result += PIECE_VALUES[piece] *
                  (pop_count(piece_type[piece] & color[us]) as i16 -
                   pop_count(piece_type[piece] & color[them]) as i16);
    }
    let mut hasher = SipHasher::new();
    hasher.write_u64(board.occupied());
    result + (hasher.finish() >> 59) as i16
}

// use rand;
// use rand::distributions::{Sample, Range};
// let mut rng = rand::thread_rng();
// let mut between = Range::new(0, 10);
// let x = between.sample(&mut rng);
<|endoftext|>


<commit_before>//! Electric current (base unit ampere, A1).

quantity! {
    /// Electric current (base unit ampere, A1).
    quantity: ElectricCurrent; "electric current";
    /// Amount of substance dimension, mol1.
    dimension: ISQ<
        Z0,     // length
        Z0,     // mass
        Z0,     // time
        P1,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        @yottaampere: prefix!(yotta); "YA", "yottaampere", "yottaamperes";
        @zettaampere: prefix!(zetta); "ZA", "zettaampere", "zettaamperes";
        @exaampere: prefix!(exa); "EA", "exaampere", "exaamperes";
        @petaampere: prefix!(peta); "PA", "petaampere", "petaamperes";
        @teraampere: prefix!(tera); "TA", "teraampere", "teraamperes";
        @gigaampere: prefix!(giga); "GA", "gigaampere", "gigaamperes";
        @megaampere: prefix!(mega); "MA", "megaampere", "megaamperes";
        @kiloampere: prefix!(kilo); "kA", "kiloampere", "kiloamperes";
        @hectoampere: prefix!(hecto); "hA", "hectoampere", "hectoamperes";
        @decaampere: prefix!(deca); "daA", "decaampere", "decaamperes";
        /// The ampere is the constant current which, if maintained in two straight parallel
        /// conductors of infinite length, of negligible circular cross-section, and placed 1 meter
        /// apart in vacuum, would produce between these conductors a force equal to 2E-7 newton per
        /// meter of length.
        @ampere: prefix!(none); "A", "ampere", "amperes";
        @deciampere: prefix!(deci); "dA", "deciampere", "deciamperes";
        @centiampere: prefix!(centi); "cA", "centiampere", "centiamperes";
        @milliampere: prefix!(milli); "mA", "millampere", "millamperes";
        @microampere: prefix!(micro); "A", "ampere", "amperes";
        @nanoampere: prefix!(nano); "A", "ampere", "amperes";
        @picoampere: prefix!(pico); "A", "ampere", "amperes";
        @femtoampere: prefix!(femto); "A", "ampere", "amperes";
        @attoampere: prefix!(atto); "A", "ampere", "amperes";
        @zeptoampere: prefix!(zepto); "A", "ampere", "amperes";
        @yoctoampere: prefix!(yocto); "A", "ampere", "amperes";
    }
}
<commit_msg>Fix current documentation copy-paste error.<commit_after>//! Electric current (base unit ampere, A1).

quantity! {
    /// Electric current (base unit ampere, A1).
    quantity: ElectricCurrent; "electric current";
    /// Electric current dimension, A1.
    dimension: ISQ<
        Z0,     // length
        Z0,     // mass
        Z0,     // time
        P1,     // electric current
        Z0,     // thermodynamic temperature
        Z0,     // amount of substance
        Z0>;    // luminous intensity
    units {
        @yottaampere: prefix!(yotta); "YA", "yottaampere", "yottaamperes";
        @zettaampere: prefix!(zetta); "ZA", "zettaampere", "zettaamperes";
        @exaampere: prefix!(exa); "EA", "exaampere", "exaamperes";
        @petaampere: prefix!(peta); "PA", "petaampere", "petaamperes";
        @teraampere: prefix!(tera); "TA", "teraampere", "teraamperes";
        @gigaampere: prefix!(giga); "GA", "gigaampere", "gigaamperes";
        @megaampere: prefix!(mega); "MA", "megaampere", "megaamperes";
        @kiloampere: prefix!(kilo); "kA", "kiloampere", "kiloamperes";
        @hectoampere: prefix!(hecto); "hA", "hectoampere", "hectoamperes";
        @decaampere: prefix!(deca); "daA", "decaampere", "decaamperes";
        /// The ampere is the constant current which, if maintained in two straight parallel
        /// conductors of infinite length, of negligible circular cross-section, and placed 1 meter
        /// apart in vacuum, would produce between these conductors a force equal to 2E-7 newton per
        /// meter of length.
        @ampere: prefix!(none); "A", "ampere", "amperes";
        @deciampere: prefix!(deci); "dA", "deciampere", "deciamperes";
        @centiampere: prefix!(centi); "cA", "centiampere", "centiamperes";
        @milliampere: prefix!(milli); "mA", "millampere", "millamperes";
        @microampere: prefix!(micro); "A", "ampere", "amperes";
        @nanoampere: prefix!(nano); "A", "ampere", "amperes";
        @picoampere: prefix!(pico); "A", "ampere", "amperes";
        @femtoampere: prefix!(femto); "A", "ampere", "amperes";
        @attoampere: prefix!(atto); "A", "ampere", "amperes";
        @zeptoampere: prefix!(zepto); "A", "ampere", "amperes";
        @yoctoampere: prefix!(yocto); "A", "ampere", "amperes";
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove fixed fixme<commit_after><|endoftext|>


<commit_before>extern crate "cargo-registry" as cargo_registry;
extern crate migrate;
extern crate postgres;
extern crate r2d2;

use std::os;
use migrate::Migration;
use postgres::{PostgresTransaction, PostgresResult};

use cargo_registry::krate::Crate;

fn main() {
    let db_config = r2d2::Config {
        pool_size: 1,
        helper_tasks: 1,
        test_on_check_out: false,
    };
    let database = cargo_registry::db::pool(env("DATABASE_URL").as_slice(),
                                            db_config);
    let conn = database.get().unwrap();
    let migrations = migrations();

    if os::args().as_slice().get(1).map(|s| s.as_slice()) == Some("rollback") {
        rollback(conn.transaction().unwrap(), migrations).unwrap();
    } else {
        apply(conn.transaction().unwrap(), migrations).unwrap();
    }

    fn env(s: &str) -> String {
        match os::getenv(s) {
            Some(s) => s,
            None => fail!("must have `{}` defined", s),
        }
    }
}

fn apply(tx: PostgresTransaction,
         migrations: Vec<Migration>) -> PostgresResult<()> {
    let mut mgr = try!(migrate::Manager::new(tx));
    for m in migrations.into_iter() {
        try!(mgr.apply(m));
    }
    mgr.set_commit();
    mgr.finish()
}

fn rollback(tx: PostgresTransaction,
            migrations: Vec<Migration>) -> PostgresResult<()> {
    let mut mgr = try!(migrate::Manager::new(tx));
    for m in migrations.into_iter().rev() {
        if mgr.contains(m.version()) {
            try!(mgr.rollback(m));
            break
        }
    }
    mgr.set_commit();
    mgr.finish()
}

fn migrations() -> Vec<Migration> {
    // Generate a new id via `date +"%Y%m%d%H%M%S"`
    vec![
        Migration::add_table(20140924113530, "users", "
            id              SERIAL PRIMARY KEY,
            email           VARCHAR NOT NULL UNIQUE,
            gh_access_token VARCHAR NOT NULL,
            api_token       VARCHAR NOT NULL
        "),
        Migration::add_table(20140924114003, "packages", "
            id              SERIAL PRIMARY KEY,
            name            VARCHAR NOT NULL UNIQUE,
            user_id         INTEGER NOT NULL
        "),
        Migration::add_table(20140924114059, "versions", "
            id              SERIAL PRIMARY KEY,
            package_id      INTEGER NOT NULL,
            num             VARCHAR NOT NULL
        "),
        Migration::run(20140924115329,
                       format!("ALTER TABLE versions ADD CONSTRAINT \
                                unique_num UNIQUE (package_id, num)"),
                       format!("ALTER TABLE versions DROP CONSTRAINT \
                                unique_num")),
        Migration::add_table(20140924120803, "version_dependencies", "
            version_id      INTEGER NOT NULL,
            depends_on_id   INTEGER NOT NULL
        "),
        Migration::add_column(20140925132248, "packages", "updated_at",
                              "TIMESTAMP NOT NULL DEFAULT now()"),
        Migration::add_column(20140925132249, "packages", "created_at",
                              "TIMESTAMP NOT NULL DEFAULT now()"),
        Migration::new(20140925132250, proc(tx) {
            try!(tx.execute("UPDATE packages SET updated_at = now() \
                             WHERE updated_at IS NULL", []));
            try!(tx.execute("UPDATE packages SET created_at = now() \
                             WHERE created_at IS NULL", []));
            Ok(())
        }, proc(_) Ok(())),
        Migration::add_column(20140925132251, "versions", "updated_at",
                              "TIMESTAMP NOT NULL DEFAULT now()"),
        Migration::add_column(20140925132252, "versions", "created_at",
                              "TIMESTAMP NOT NULL DEFAULT now()"),
        Migration::new(20140925132253, proc(tx) {
            try!(tx.execute("UPDATE versions SET updated_at = now() \
                             WHERE updated_at IS NULL", []));
            try!(tx.execute("UPDATE versions SET created_at = now() \
                             WHERE created_at IS NULL", []));
            Ok(())
        }, proc(_) Ok(())),
        Migration::new(20140925132254, proc(tx) {
            try!(tx.execute("ALTER TABLE versions ALTER COLUMN updated_at \
                             DROP DEFAULT", []));
            try!(tx.execute("ALTER TABLE versions ALTER COLUMN created_at \
                             DROP DEFAULT", []));
            try!(tx.execute("ALTER TABLE packages ALTER COLUMN updated_at \
                             DROP DEFAULT", []));
            try!(tx.execute("ALTER TABLE packages ALTER COLUMN created_at \
                             DROP DEFAULT", []));
            Ok(())
        }, proc(_) Ok(())),
        Migration::add_table(20140925153704, "metadata", "
            total_downloads        BIGINT NOT NULL
        "),
        Migration::new(20140925153705, proc(tx) {
            try!(tx.execute("INSERT INTO metadata (total_downloads) \
                             VALUES ($1)", &[&0i64]));
            Ok(())
        }, proc(tx) {
            try!(tx.execute("DELETE FROM metadata", [])); Ok(())
        }),
        Migration::add_column(20140925161623, "packages", "downloads",
                              "INTEGER NOT NULL DEFAULT 0"),
        Migration::add_column(20140925161624, "versions", "downloads",
                              "INTEGER NOT NULL DEFAULT 0"),
        Migration::new(20140925161625, proc(tx) {
            try!(tx.execute("ALTER TABLE versions ALTER COLUMN downloads \
                             DROP DEFAULT", []));
            try!(tx.execute("ALTER TABLE packages ALTER COLUMN downloads \
                             DROP DEFAULT", []));
            Ok(())
        }, proc(_) Ok(())),
        Migration::add_column(20140926130044, "packages", "max_version",
                              "VARCHAR"),
        Migration::new(20140926130045, proc(tx) {
            let stmt = try!(tx.prepare("SELECT * FROM packages"));
            for row in try!(stmt.query(&[])) {
                let pkg = Crate::from_row(&row);
                let versions = pkg.versions(tx).unwrap();
                let v = versions.iter().max_by(|v| &v.num).unwrap();
                let max = v.num.to_string();
                try!(tx.execute("UPDATE packages SET max_version = $1 \
                                 WHERE id = $2",
                                &[&max, &pkg.id]));
            }
            Ok(())
        }, proc(_) Ok(())),
        Migration::new(20140926130046, proc(tx) {
            try!(tx.execute("ALTER TABLE versions ALTER COLUMN downloads \
                             SET NOT NULL", []));
            Ok(())
        }, proc(tx) {
            try!(tx.execute("ALTER TABLE versions ALTER COLUMN downloads \
                             DROP NOT NULL", []));
            Ok(())
        }),
        Migration::new(20140926174020, proc(tx) {
            try!(tx.execute("ALTER TABLE packages RENAME TO crates", []));
            try!(tx.execute("ALTER TABLE versions RENAME COLUMN package_id \
                             TO crate_id", []));
            Ok(())
        }, proc(tx) {
            try!(tx.execute("ALTER TABLE crates RENAME TO packages", []));
            try!(tx.execute("ALTER TABLE versions RENAME COLUMN crate_id \
                             TO package_id", []));
            Ok(())
        }),
    ]
}
<commit_msg>Add indexes to crate columns<commit_after>extern crate "cargo-registry" as cargo_registry;
extern crate migrate;
extern crate postgres;
extern crate r2d2;

use std::os;
use migrate::Migration;
use postgres::{PostgresTransaction, PostgresResult};

use cargo_registry::krate::Crate;

fn main() {
    let db_config = r2d2::Config {
        pool_size: 1,
        helper_tasks: 1,
        test_on_check_out: false,
    };
    let database = cargo_registry::db::pool(env("DATABASE_URL").as_slice(),
                                            db_config);
    let conn = database.get().unwrap();
    let migrations = migrations();

    if os::args().as_slice().get(1).map(|s| s.as_slice()) == Some("rollback") {
        rollback(conn.transaction().unwrap(), migrations).unwrap();
    } else {
        apply(conn.transaction().unwrap(), migrations).unwrap();
    }

    fn env(s: &str) -> String {
        match os::getenv(s) {
            Some(s) => s,
            None => fail!("must have `{}` defined", s),
        }
    }
}

fn apply(tx: PostgresTransaction,
         migrations: Vec<Migration>) -> PostgresResult<()> {
    let mut mgr = try!(migrate::Manager::new(tx));
    for m in migrations.into_iter() {
        try!(mgr.apply(m));
    }
    mgr.set_commit();
    mgr.finish()
}

fn rollback(tx: PostgresTransaction,
            migrations: Vec<Migration>) -> PostgresResult<()> {
    let mut mgr = try!(migrate::Manager::new(tx));
    for m in migrations.into_iter().rev() {
        if mgr.contains(m.version()) {
            try!(mgr.rollback(m));
            break
        }
    }
    mgr.set_commit();
    mgr.finish()
}

fn migrations() -> Vec<Migration> {
    // Generate a new id via `date +"%Y%m%d%H%M%S"`
    vec![
        Migration::add_table(20140924113530, "users", "
            id              SERIAL PRIMARY KEY,
            email           VARCHAR NOT NULL UNIQUE,
            gh_access_token VARCHAR NOT NULL,
            api_token       VARCHAR NOT NULL
        "),
        Migration::add_table(20140924114003, "packages", "
            id              SERIAL PRIMARY KEY,
            name            VARCHAR NOT NULL UNIQUE,
            user_id         INTEGER NOT NULL
        "),
        Migration::add_table(20140924114059, "versions", "
            id              SERIAL PRIMARY KEY,
            package_id      INTEGER NOT NULL,
            num             VARCHAR NOT NULL
        "),
        Migration::run(20140924115329,
                       format!("ALTER TABLE versions ADD CONSTRAINT \
                                unique_num UNIQUE (package_id, num)"),
                       format!("ALTER TABLE versions DROP CONSTRAINT \
                                unique_num")),
        Migration::add_table(20140924120803, "version_dependencies", "
            version_id      INTEGER NOT NULL,
            depends_on_id   INTEGER NOT NULL
        "),
        Migration::add_column(20140925132248, "packages", "updated_at",
                              "TIMESTAMP NOT NULL DEFAULT now()"),
        Migration::add_column(20140925132249, "packages", "created_at",
                              "TIMESTAMP NOT NULL DEFAULT now()"),
        Migration::new(20140925132250, proc(tx) {
            try!(tx.execute("UPDATE packages SET updated_at = now() \
                             WHERE updated_at IS NULL", []));
            try!(tx.execute("UPDATE packages SET created_at = now() \
                             WHERE created_at IS NULL", []));
            Ok(())
        }, proc(_) Ok(())),
        Migration::add_column(20140925132251, "versions", "updated_at",
                              "TIMESTAMP NOT NULL DEFAULT now()"),
        Migration::add_column(20140925132252, "versions", "created_at",
                              "TIMESTAMP NOT NULL DEFAULT now()"),
        Migration::new(20140925132253, proc(tx) {
            try!(tx.execute("UPDATE versions SET updated_at = now() \
                             WHERE updated_at IS NULL", []));
            try!(tx.execute("UPDATE versions SET created_at = now() \
                             WHERE created_at IS NULL", []));
            Ok(())
        }, proc(_) Ok(())),
        Migration::new(20140925132254, proc(tx) {
            try!(tx.execute("ALTER TABLE versions ALTER COLUMN updated_at \
                             DROP DEFAULT", []));
            try!(tx.execute("ALTER TABLE versions ALTER COLUMN created_at \
                             DROP DEFAULT", []));
            try!(tx.execute("ALTER TABLE packages ALTER COLUMN updated_at \
                             DROP DEFAULT", []));
            try!(tx.execute("ALTER TABLE packages ALTER COLUMN created_at \
                             DROP DEFAULT", []));
            Ok(())
        }, proc(_) Ok(())),
        Migration::add_table(20140925153704, "metadata", "
            total_downloads        BIGINT NOT NULL
        "),
        Migration::new(20140925153705, proc(tx) {
            try!(tx.execute("INSERT INTO metadata (total_downloads) \
                             VALUES ($1)", &[&0i64]));
            Ok(())
        }, proc(tx) {
            try!(tx.execute("DELETE FROM metadata", [])); Ok(())
        }),
        Migration::add_column(20140925161623, "packages", "downloads",
                              "INTEGER NOT NULL DEFAULT 0"),
        Migration::add_column(20140925161624, "versions", "downloads",
                              "INTEGER NOT NULL DEFAULT 0"),
        Migration::new(20140925161625, proc(tx) {
            try!(tx.execute("ALTER TABLE versions ALTER COLUMN downloads \
                             DROP DEFAULT", []));
            try!(tx.execute("ALTER TABLE packages ALTER COLUMN downloads \
                             DROP DEFAULT", []));
            Ok(())
        }, proc(_) Ok(())),
        Migration::add_column(20140926130044, "packages", "max_version",
                              "VARCHAR"),
        Migration::new(20140926130045, proc(tx) {
            let stmt = try!(tx.prepare("SELECT * FROM packages"));
            for row in try!(stmt.query(&[])) {
                let pkg = Crate::from_row(&row);
                let versions = pkg.versions(tx).unwrap();
                let v = versions.iter().max_by(|v| &v.num).unwrap();
                let max = v.num.to_string();
                try!(tx.execute("UPDATE packages SET max_version = $1 \
                                 WHERE id = $2",
                                &[&max, &pkg.id]));
            }
            Ok(())
        }, proc(_) Ok(())),
        Migration::new(20140926130046, proc(tx) {
            try!(tx.execute("ALTER TABLE versions ALTER COLUMN downloads \
                             SET NOT NULL", []));
            Ok(())
        }, proc(tx) {
            try!(tx.execute("ALTER TABLE versions ALTER COLUMN downloads \
                             DROP NOT NULL", []));
            Ok(())
        }),
        Migration::new(20140926174020, proc(tx) {
            try!(tx.execute("ALTER TABLE packages RENAME TO crates", []));
            try!(tx.execute("ALTER TABLE versions RENAME COLUMN package_id \
                             TO crate_id", []));
            Ok(())
        }, proc(tx) {
            try!(tx.execute("ALTER TABLE crates RENAME TO packages", []));
            try!(tx.execute("ALTER TABLE versions RENAME COLUMN crate_id \
                             TO package_id", []));
            Ok(())
        }),
        Migration::run(20140929103749,
                       "CREATE INDEX crate_updated_at ON crates (updated_at)".to_string(),
                       "DROP INDEX crate_updated_at".to_string()),
        Migration::run(20140929103750,
                       "CREATE INDEX crate_created_at ON crates (created_at)".to_string(),
                       "DROP INDEX crate_created_at".to_string()),
        Migration::run(20140929103751,
                       "CREATE INDEX crate_downloads ON crates (downloads)".to_string(),
                       "DROP INDEX crate_downloads".to_string()),
    ]
}
<|endoftext|>


<commit_before>use story_builder::story_builder::*;
use story_builder::article_provider::*;
use std::collections::HashMap;
use std::rc::Rc;

static EXPECTED_SUGGESTION: &'static str = "Cannot find wikipedia article for <not-found>, try one of the following suggestions:\r\n\
- Suggestion 1\r\n\
- Suggestion 2\r\n\
- Suggestion 3\r\n";

#[test]
/// For: build_suggestions_msg
fn build_suggestions_msg_is_working() {
    struct TestProvider {}
    impl ArticleProvider for TestProvider {
        #[allow(unused_variables)]
        fn get(&self, topic: &str) -> Option<Box<Article>> {
            panic!("get() should never be called in this test.");
        }
        #[allow(unused_variables)]
        fn search(&self, topic: &str) -> Vec<String> {
            vec!["Suggestion 1".to_owned(),
            "Suggestion 2".to_owned(),
            "Suggestion 3".to_owned()]
        }
    }
    let provider = TestProvider {};
    let story_builder = StoryBuilder::new(&provider);

    assert_eq!(story_builder.build_suggestions_msg("not-found"), EXPECTED_SUGGESTION);
}

#[test]
/// For: build_story
fn build_story_cannot_find_first_article_suggest() {
    struct TestArticle {
        topics: Vec<Reference>
    }
    impl Article for TestArticle {
        fn get_related_references(&self) -> &Vec<Reference> {&self.topics}
    }
    struct TestProvider {}
    impl ArticleProvider for TestProvider {
        fn get(&self, topic: &str) -> Option<Box<Article>> {
            if topic == "found" {
                Some(Box::new(TestArticle {topics: vec![]}))
            }
            else {
                None
            }
        }
        #[allow(unused_variables)]
        fn search(&self, topic: &str) -> Vec<String> {
            vec!["Suggestion 1".to_owned(),
            "Suggestion 2".to_owned(),
            "Suggestion 3".to_owned()]
        }
    }

    let provider = TestProvider {};
    let story_builder = StoryBuilder::new(&provider);
    assert_eq!(story_builder.build_story("not-found", "found"), Err(EXPECTED_SUGGESTION.to_owned()));
}

#[test]
/// For: build_story
fn build_story_cannot_find_second_article_suggest() {
    struct TestArticle {
        topics: Vec<Reference>
    }
    impl Article for TestArticle {
        fn get_related_references(&self) -> &Vec<Reference> {&self.topics}
    }
    struct TestProvider {}
    impl ArticleProvider for TestProvider {
        fn get(&self, topic: &str) -> Option<Box<Article>> {
            if topic == "found"
                {Some(Box::new(TestArticle {topics: vec![]}))}
            else
                {None}
        }
        #[allow(unused_variables)]
        fn search(&self, topic: &str) -> Vec<String> {
            vec!["Suggestion 1".to_owned(),
            "Suggestion 2".to_owned(),
            "Suggestion 3".to_owned()]
        }
    }

    let provider = TestProvider {};
    let story_builder = StoryBuilder::new(&provider);
    assert_eq!(story_builder.build_story("found", "not-found"), Err(EXPECTED_SUGGESTION.to_owned()));
}

#[test]
/// For: build_story
fn build_story_from_same_start_and_end_should_err() {
    struct TestProvider {}
    impl ArticleProvider for TestProvider {
        #[allow(unused_variables)]
        fn get(&self, topic: &str) -> Option<Box<Article>> {panic!("get() should not get called in this test.")}
        #[allow(unused_variables)]
        fn search(&self, topic: &str) -> Vec<String> {panic!("get() should not get called in this test.")}
    }
    let provider = TestProvider {};
    let story_builder = StoryBuilder::new(&provider);
    assert_eq!(story_builder.build_story("similar topic", "similar topic"),
               Err("No story to build; same start and end topics.".to_owned()));
}

#[test]
/// For: build_story
fn build_story_empty_start_topic_should_err() {
    struct TestProvider {}
    impl ArticleProvider for TestProvider {
        #[allow(unused_variables)]
        fn get(&self, topic: &str) -> Option<Box<Article>> {panic!("get() should not get called in this test.")}
        #[allow(unused_variables)]
        fn search(&self, topic: &str) -> Vec<String> {panic!("get() should not get called in this test.")}
    }
    let provider = TestProvider {};
    let story_builder = StoryBuilder::new(&provider);
    assert_eq!(story_builder.build_story("", "Other topic"),
               Err("Missing start topic.".to_owned()));
}

#[test]
/// For: build_story
fn build_story_empty_end_topic_should_err() {
    struct TestProvider {}
    impl ArticleProvider for TestProvider {
        #[allow(unused_variables)]
        fn get(&self, topic: &str) -> Option<Box<Article>> {panic!("get() should not get called in this test.")}
        #[allow(unused_variables)]
        fn search(&self, topic: &str) -> Vec<String> {panic!("get() should not get called in this test.")}
    }
    let provider = TestProvider {};
    let story_builder = StoryBuilder::new(&provider);
    assert_eq!(story_builder.build_story("First topic", ""),
               Err("Missing end topic.".to_owned()));
}

#[test]
/// For: build_story
fn build_story_end_topic_found_in_start_article() {
    let mut prebuilt_rels = Rc::new(HashMap::new());
    Rc::get_mut(&mut prebuilt_rels).unwrap().insert("start", vec![Reference {topic: "rel1".to_owned(), paragraph: "Paragraph for rel1.".to_owned()},
                                                                  Reference {topic: "rel2".to_owned(), paragraph: "Paragraph for rel1.".to_owned()},
                                                                  Reference {topic: "end".to_owned(), paragraph: "Paragraph for end.".to_owned()},
                                                                  Reference {topic: "rel3".to_owned(), paragraph: "Paragraph for rel3.".to_owned()}]);
    struct TestArticle {
        topic: String,
        prebuilt_rels: Rc<HashMap<&'static str, Vec<Reference>>>,
    }

    impl TestArticle {
        fn new(topic: String, prebuilt_rels: Rc<HashMap<&'static str, Vec<Reference>>>) -> TestArticle {
            TestArticle {topic, prebuilt_rels}
        }
    }

    impl Article for TestArticle {
            fn get_related_references(&self) -> &Vec<Reference> {
            self.prebuilt_rels.get::<str>(&self.topic).expect("Tried to access a node that doesn't exist!")
        }
    }
    struct TestProvider {
        prebuilt_rels: Rc<HashMap<&'static str, Vec<Reference>>>
    }
    impl TestProvider {
        fn new(prebuilt_rels: Rc<HashMap<&'static str, Vec<Reference>>>) -> TestProvider {
            TestProvider {prebuilt_rels}
        }
    }
    impl ArticleProvider for TestProvider {
        fn get(&self, topic: &str) -> Option<Box<Article>> {
                let new_rels: Rc<HashMap<&'static str, Vec<Reference>>> = self.prebuilt_rels.clone();
                Some(Box::new(TestArticle::new(topic.to_owned(), new_rels)))
        }
        fn search(&self, topic: &str) -> Vec<String> {panic!("search() should not be called in this test.");}
    }
    let provider = TestProvider::new(prebuilt_rels.clone());
    let story_builder = StoryBuilder::new(&provider);
    assert_eq!(story_builder.build_story("start", "end"), Ok("Paragraph with end in it.\r\n".to_owned()));
}
<commit_msg>fixed test<commit_after>use story_builder::story_builder::*;
use story_builder::article_provider::*;
use std::collections::HashMap;
use std::rc::Rc;

static EXPECTED_SUGGESTION: &'static str = "Cannot find wikipedia article for <not-found>, try one of the following suggestions:\r\n\
- Suggestion 1\r\n\
- Suggestion 2\r\n\
- Suggestion 3\r\n";

#[test]
/// For: build_suggestions_msg
fn build_suggestions_msg_is_working() {
    struct TestProvider {}
    impl ArticleProvider for TestProvider {
        #[allow(unused_variables)]
        fn get(&self, topic: &str) -> Option<Box<Article>> {
            panic!("get() should never be called in this test.");
        }
        #[allow(unused_variables)]
        fn search(&self, topic: &str) -> Vec<String> {
            vec!["Suggestion 1".to_owned(),
            "Suggestion 2".to_owned(),
            "Suggestion 3".to_owned()]
        }
    }
    let provider = TestProvider {};
    let story_builder = StoryBuilder::new(&provider);

    assert_eq!(story_builder.build_suggestions_msg("not-found"), EXPECTED_SUGGESTION);
}

#[test]
/// For: build_story
fn build_story_cannot_find_first_article_suggest() {
    struct TestArticle {
        topics: Vec<Reference>
    }
    impl Article for TestArticle {
        fn get_related_references(&self) -> &Vec<Reference> {&self.topics}
    }
    struct TestProvider {}
    impl ArticleProvider for TestProvider {
        fn get(&self, topic: &str) -> Option<Box<Article>> {
            if topic == "found" {
                Some(Box::new(TestArticle {topics: vec![]}))
            }
            else {
                None
            }
        }
        #[allow(unused_variables)]
        fn search(&self, topic: &str) -> Vec<String> {
            vec!["Suggestion 1".to_owned(),
            "Suggestion 2".to_owned(),
            "Suggestion 3".to_owned()]
        }
    }

    let provider = TestProvider {};
    let story_builder = StoryBuilder::new(&provider);
    assert_eq!(story_builder.build_story("not-found", "found"), Err(EXPECTED_SUGGESTION.to_owned()));
}

#[test]
/// For: build_story
fn build_story_cannot_find_second_article_suggest() {
    struct TestArticle {
        topics: Vec<Reference>
    }
    impl Article for TestArticle {
        fn get_related_references(&self) -> &Vec<Reference> {&self.topics}
    }
    struct TestProvider {}
    impl ArticleProvider for TestProvider {
        fn get(&self, topic: &str) -> Option<Box<Article>> {
            if topic == "found"
                {Some(Box::new(TestArticle {topics: vec![]}))}
            else
                {None}
        }
        #[allow(unused_variables)]
        fn search(&self, topic: &str) -> Vec<String> {
            vec!["Suggestion 1".to_owned(),
            "Suggestion 2".to_owned(),
            "Suggestion 3".to_owned()]
        }
    }

    let provider = TestProvider {};
    let story_builder = StoryBuilder::new(&provider);
    assert_eq!(story_builder.build_story("found", "not-found"), Err(EXPECTED_SUGGESTION.to_owned()));
}

#[test]
/// For: build_story
fn build_story_from_same_start_and_end_should_err() {
    struct TestProvider {}
    impl ArticleProvider for TestProvider {
        #[allow(unused_variables)]
        fn get(&self, topic: &str) -> Option<Box<Article>> {panic!("get() should not get called in this test.")}
        #[allow(unused_variables)]
        fn search(&self, topic: &str) -> Vec<String> {panic!("get() should not get called in this test.")}
    }
    let provider = TestProvider {};
    let story_builder = StoryBuilder::new(&provider);
    assert_eq!(story_builder.build_story("similar topic", "similar topic"),
               Err("No story to build; same start and end topics.".to_owned()));
}

#[test]
/// For: build_story
fn build_story_empty_start_topic_should_err() {
    struct TestProvider {}
    impl ArticleProvider for TestProvider {
        #[allow(unused_variables)]
        fn get(&self, topic: &str) -> Option<Box<Article>> {panic!("get() should not get called in this test.")}
        #[allow(unused_variables)]
        fn search(&self, topic: &str) -> Vec<String> {panic!("get() should not get called in this test.")}
    }
    let provider = TestProvider {};
    let story_builder = StoryBuilder::new(&provider);
    assert_eq!(story_builder.build_story("", "Other topic"),
               Err("Missing start topic.".to_owned()));
}

#[test]
/// For: build_story
fn build_story_empty_end_topic_should_err() {
    struct TestProvider {}
    impl ArticleProvider for TestProvider {
        #[allow(unused_variables)]
        fn get(&self, topic: &str) -> Option<Box<Article>> {panic!("get() should not get called in this test.")}
        #[allow(unused_variables)]
        fn search(&self, topic: &str) -> Vec<String> {panic!("get() should not get called in this test.")}
    }
    let provider = TestProvider {};
    let story_builder = StoryBuilder::new(&provider);
    assert_eq!(story_builder.build_story("First topic", ""),
               Err("Missing end topic.".to_owned()));
}

#[test]
/// For: build_story
fn build_story_end_topic_found_in_start_article() {
    let mut prebuilt_rels = Rc::new(HashMap::new());
    Rc::get_mut(&mut prebuilt_rels).unwrap().insert("start", vec![Reference {topic: "rel1".to_owned(), paragraph: "Paragraph for rel1.".to_owned()},
                                                                  Reference {topic: "rel2".to_owned(), paragraph: "Paragraph for rel1.".to_owned()},
                                                                  Reference {topic: "end".to_owned(), paragraph: "Paragraph for end.".to_owned()},
                                                                  Reference {topic: "rel3".to_owned(), paragraph: "Paragraph for rel3.".to_owned()}]);
    struct TestArticle {
        topic: String,
        prebuilt_rels: Rc<HashMap<&'static str, Vec<Reference>>>,
    }

    impl TestArticle {
        fn new(topic: String, prebuilt_rels: Rc<HashMap<&'static str, Vec<Reference>>>) -> TestArticle {
            TestArticle {topic, prebuilt_rels}
        }
    }

    impl Article for TestArticle {
            fn get_related_references(&self) -> &Vec<Reference> {
            self.prebuilt_rels.get::<str>(&self.topic).expect("Tried to access a node that doesn't exist!")
        }
    }
    struct TestProvider {
        prebuilt_rels: Rc<HashMap<&'static str, Vec<Reference>>>
    }
    impl TestProvider {
        fn new(prebuilt_rels: Rc<HashMap<&'static str, Vec<Reference>>>) -> TestProvider {
            TestProvider {prebuilt_rels}
        }
    }
    impl ArticleProvider for TestProvider {
        fn get(&self, topic: &str) -> Option<Box<Article>> {
                let new_rels: Rc<HashMap<&'static str, Vec<Reference>>> = self.prebuilt_rels.clone();
                Some(Box::new(TestArticle::new(topic.to_owned(), new_rels)))
        }
        fn search(&self, topic: &str) -> Vec<String> {panic!("search() should not be called in this test.");}
    }
    let provider = TestProvider::new(prebuilt_rels.clone());
    let story_builder = StoryBuilder::new(&provider);
    assert_eq!(story_builder.build_story("start", "end"), Ok("Paragraph for end.\r\n".to_owned()));
}
<|endoftext|>


<commit_before><commit_msg>GetInterfaceDescriptionArgs: make fields public<commit_after><|endoftext|>


<commit_before><commit_msg>Save and load game with json<commit_after><|endoftext|>


<commit_before>use cargo::ops;
use cargo::util::{CliResult, Config};

#[derive(RustcDecodable)]
struct Options {
    flag_bin: Vec<String>,
    flag_root: Option<String>,
    flag_verbose: bool,
    flag_quiet: bool,
    flag_color: Option<String>,

    arg_spec: String,
}

pub const USAGE: &'static str = "
Remove a Rust binary

Usage:
    cargo uninstall [options] <spec>

Options:
    -h, --help                Print this message
    --root DIR                Directory to uninstall packages from
    --bin NAME                Only uninstall the binary NAME
    -v, --verbose             Use verbose output
    -q, --quiet               Less output printed to stdout
    --color WHEN              Coloring: auto, always, never

The argument SPEC is a package id specification (see `cargo help pkgid`) to
specify which crate should be uninstalled. By default all binaries are
uninstalled for a crate but the `--bin` and `--example` flags can be used to
only uninstall particular binaries.
";

pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
    try!(config.shell().set_verbosity(options.flag_verbose, options.flag_quiet));
    try!(config.shell().set_color_config(options.flag_color.as_ref().map(|s| &s[..])));

    let root = options.flag_root.as_ref().map(|s| &s[..]);
    try!(ops::uninstall(root, &options.arg_spec, &options.flag_bin, config));
    Ok(None)
}

<commit_msg>Fix `cargo-uninstall`.<commit_after>use cargo::ops;
use cargo::util::{CliResult, Config};

#[derive(RustcDecodable)]
struct Options {
    flag_bin: Vec<String>,
    flag_root: Option<String>,
    flag_verbose: bool,
    flag_quiet: bool,
    flag_color: Option<String>,

    arg_spec: String,
}

pub const USAGE: &'static str = "
Remove a Rust binary

Usage:
    cargo uninstall [options] <spec>
    cargo uninstall (-h | --help)

Options:
    -h, --help                Print this message
    --root DIR                Directory to uninstall packages from
    --bin NAME                Only uninstall the binary NAME
    -v, --verbose             Use verbose output
    -q, --quiet               Less output printed to stdout
    --color WHEN              Coloring: auto, always, never

The argument SPEC is a package id specification (see `cargo help pkgid`) to
specify which crate should be uninstalled. By default all binaries are
uninstalled for a crate but the `--bin` and `--example` flags can be used to
only uninstall particular binaries.
";

pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
    try!(config.shell().set_verbosity(options.flag_verbose, options.flag_quiet));
    try!(config.shell().set_color_config(options.flag_color.as_ref().map(|s| &s[..])));

    let root = options.flag_root.as_ref().map(|s| &s[..]);
    try!(ops::uninstall(root, &options.arg_spec, &options.flag_bin, config));
    Ok(None)
}

<|endoftext|>


<commit_before>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;
use std::fs::File;
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
use std::sync::Arc;
use std::time::Duration;
use std::{io, thread};

use crate::lmdb;

use crate::core::core;
use crate::core::core::hash::Hash;
use crate::core::global;
use crate::core::pow::Difficulty;
use crate::handshake::Handshake;
use crate::peer::Peer;
use crate::peers::Peers;
use crate::store::PeerStore;
use crate::types::{Capabilities, ChainAdapter, Error, NetAdapter, P2PConfig, TxHashSetRead};
use crate::util::{Mutex, StopState};
use chrono::prelude::{DateTime, Utc};

/// P2P server implementation, handling bootstrapping to find and connect to
/// peers, receiving connections from other peers and keep track of all of them.
pub struct Server {
	pub config: P2PConfig,
	capabilities: Capabilities,
	handshake: Arc<Handshake>,
	pub peers: Arc<Peers>,
	stop_state: Arc<Mutex<StopState>>,
}

// TODO TLS
impl Server {
	/// Creates a new idle p2p server with no peers
	pub fn new(
		db_env: Arc<lmdb::Environment>,
		capab: Capabilities,
		config: P2PConfig,
		adapter: Arc<dyn ChainAdapter>,
		genesis: Hash,
		stop_state: Arc<Mutex<StopState>>,
	) -> Result<Server, Error> {
		Ok(Server {
			config: config.clone(),
			capabilities: capab,
			handshake: Arc::new(Handshake::new(genesis, config.clone())),
			peers: Arc::new(Peers::new(PeerStore::new(db_env)?, adapter, config)),
			stop_state,
		})
	}

	/// Starts a new TCP server and listen to incoming connections. This is a
	/// blocking call until the TCP server stops.
	pub fn listen(&self) -> Result<(), Error> {
		// start TCP listener and handle incoming connections
		let addr = SocketAddr::new(self.config.host, self.config.port);
		let listener = TcpListener::bind(addr)?;
		listener.set_nonblocking(true)?;

		let mut connected_sockets: HashMap<SocketAddr, TcpStream> = HashMap::new();

		let sleep_time = Duration::from_millis(1);
		loop {
			// Pause peer ingress connection request. Only for tests.
			if self.stop_state.lock().is_paused() {
				thread::sleep(Duration::from_secs(1));
				continue;
			}

			match listener.accept() {
				Ok((stream, peer_addr)) => {
					if !self.check_banned(&stream) {
						let sc = stream.try_clone();
						if let Err(e) = self.handle_new_peer(stream) {
							// in theory, should be shutdown when stream gets dropped,
							// practically doesn't seem to be happening
							stream.shutdown(Shutdown::Both);
							warn!("Error accepting peer {}: {:?}", peer_addr.to_string(), e);
						} else if let Ok(s) = sc {
							connected_sockets.insert(peer_addr, s);
						}
					}
					// if any active socket not in our peers list, close it
					self.clean_lost_sockets(&mut connected_sockets);
				}
				Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
					// nothing to do, will retry in next iteration
				}
				Err(e) => {
					warn!("Couldn't establish new client connection: {:?}", e);
				}
			}
			if self.stop_state.lock().is_stopped() {
				break;
			}
			thread::sleep(sleep_time);
		}
		Ok(())
	}

	/// Asks the server to connect to a new peer. Directly returns the peer if
	/// we're already connected to the provided address.
	pub fn connect(&self, addr: &SocketAddr) -> Result<Arc<Peer>, Error> {
		if Peer::is_denied(&self.config, &addr) {
			debug!("connect_peer: peer {} denied, not connecting.", addr);
			return Err(Error::ConnectionClose);
		}

		if global::is_production_mode() {
			let hs = self.handshake.clone();
			let addrs = hs.addrs.read();
			if addrs.contains(&addr) {
				debug!("connect: ignore connecting to PeerWithSelf, addr: {}", addr);
				return Err(Error::PeerWithSelf);
			}
		}

		if let Some(p) = self.peers.get_connected_peer(addr) {
			// if we're already connected to the addr, just return the peer
			trace!("connect_peer: already connected {}", addr);
			return Ok(p);
		}

		trace!(
			"connect_peer: on {}:{}. connecting to {}",
			self.config.host,
			self.config.port,
			addr
		);
		match TcpStream::connect_timeout(addr, Duration::from_secs(10)) {
			Ok(mut stream) => {
				let addr = SocketAddr::new(self.config.host, self.config.port);
				let total_diff = self.peers.total_difficulty();

				let mut peer = Peer::connect(
					&mut stream,
					self.capabilities,
					total_diff,
					addr,
					&self.handshake,
					self.peers.clone(),
				)?;
				peer.start(stream);
				let peer = Arc::new(peer);
				self.peers.add_connected(peer.clone())?;
				Ok(peer)
			}
			Err(e) => {
				trace!(
					"connect_peer: on {}:{}. Could not connect to {}: {:?}",
					self.config.host,
					self.config.port,
					addr,
					e
				);
				Err(Error::Connection(e))
			}
		}
	}

	fn handle_new_peer(&self, mut stream: TcpStream) -> Result<(), Error> {
		let total_diff = self.peers.total_difficulty();

		// accept the peer and add it to the server map
		let mut peer = Peer::accept(
			&mut stream,
			self.capabilities,
			total_diff,
			&self.handshake,
			self.peers.clone(),
		)?;
		peer.start(stream);
		self.peers.add_connected(Arc::new(peer))?;
		Ok(())
	}

	fn check_banned(&self, stream: &TcpStream) -> bool {
		// peer has been banned, go away!
		if let Ok(peer_addr) = stream.peer_addr() {
			if self.peers.is_banned(peer_addr) {
				debug!("Peer {} banned, refusing connection.", peer_addr);
				if let Err(e) = stream.shutdown(Shutdown::Both) {
					debug!("Error shutting down conn: {:?}", e);
				}
				return true;
			}
		}
		false
	}

	/// For all kinds of exception cases, the node could accepted / initiated a peer connection successfully but
	/// failed on the Handshake protocol communication, or a connected peer was closed but without a successful
	/// clean-up on its socket, that will cause this connected (on TcpStream) peer becomes so-called "invisible" peer!
	/// i.e. a peer not included in the 'self.peers.peers' hashmap. This "invisible" peer will cause some security
	/// concern because it still can send something to this node, but without enough visibility as other connected peers.
	/// Another impact is these connections could never be closed, which make the node fully occupied by all such
	/// kind of connections and become un-connectable.
	/// This function can help to clean the peer connections which is "invisible" for this node.
	fn clean_lost_sockets(&self, sockets: &mut HashMap<SocketAddr, TcpStream>) {
		let mut lost_sockets: Vec<SocketAddr> = vec![];
		for (socket, stream) in sockets.iter() {
			if !self.peers.is_known_ip(&socket) {
				if let Ok(_) = stream.shutdown(Shutdown::Both) {
					debug!(
						"clean_lost_sockets: {} cleaned which's not in peers list",
						socket
					);
				}
				lost_sockets.push(socket.clone());
			}
		}

		for socket in lost_sockets {
			sockets.remove(&socket);
		}
	}

	pub fn stop(&self) {
		self.stop_state.lock().stop();
		self.peers.stop();
	}

	/// Pause means: stop all the current peers connection, only for tests.
	/// Note:
	/// 1. must pause the 'seed' thread also, to avoid the new egress peer connection
	/// 2. must pause the 'p2p-server' thread also, to avoid the new ingress peer connection.
	pub fn pause(&self) {
		self.peers.stop();
	}
}

/// A no-op network adapter used for testing.
pub struct DummyAdapter {}

impl ChainAdapter for DummyAdapter {
	fn total_difficulty(&self) -> Difficulty {
		Difficulty::min()
	}
	fn total_height(&self) -> u64 {
		0
	}
	fn get_transaction(&self, _h: Hash) -> Option<core::Transaction> {
		None
	}
	fn tx_kernel_received(&self, _h: Hash, _addr: SocketAddr) {}
	fn transaction_received(&self, _: core::Transaction, _stem: bool) {}
	fn compact_block_received(&self, _cb: core::CompactBlock, _addr: SocketAddr) -> bool {
		true
	}
	fn header_received(&self, _bh: core::BlockHeader, _addr: SocketAddr) -> bool {
		true
	}
	fn block_received(&self, _: core::Block, _: SocketAddr) -> bool {
		true
	}
	fn headers_received(&self, _: &[core::BlockHeader], _: SocketAddr) -> bool {
		true
	}
	fn locate_headers(&self, _: &[Hash]) -> Vec<core::BlockHeader> {
		vec![]
	}
	fn get_block(&self, _: Hash) -> Option<core::Block> {
		None
	}
	fn txhashset_read(&self, _h: Hash) -> Option<TxHashSetRead> {
		unimplemented!()
	}

	fn txhashset_receive_ready(&self) -> bool {
		false
	}

	fn txhashset_write(&self, _h: Hash, _txhashset_data: File, _peer_addr: SocketAddr) -> bool {
		false
	}

	fn txhashset_download_update(
		&self,
		_start_time: DateTime<Utc>,
		_downloaded_size: u64,
		_total_size: u64,
	) -> bool {
		false
	}
}

impl NetAdapter for DummyAdapter {
	fn find_peer_addrs(&self, _: Capabilities) -> Vec<SocketAddr> {
		vec![]
	}
	fn peer_addrs_received(&self, _: Vec<SocketAddr>) {}
	fn peer_difficulty(&self, _: SocketAddr, _: Difficulty, _: u64) {}
	fn is_banned(&self, _: SocketAddr) -> bool {
		false
	}
}
<commit_msg>Fix borrow error<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;
use std::fs::File;
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
use std::sync::Arc;
use std::time::Duration;
use std::{io, thread};

use crate::lmdb;

use crate::core::core;
use crate::core::core::hash::Hash;
use crate::core::global;
use crate::core::pow::Difficulty;
use crate::handshake::Handshake;
use crate::peer::Peer;
use crate::peers::Peers;
use crate::store::PeerStore;
use crate::types::{Capabilities, ChainAdapter, Error, NetAdapter, P2PConfig, TxHashSetRead};
use crate::util::{Mutex, StopState};
use chrono::prelude::{DateTime, Utc};

/// P2P server implementation, handling bootstrapping to find and connect to
/// peers, receiving connections from other peers and keep track of all of them.
pub struct Server {
	pub config: P2PConfig,
	capabilities: Capabilities,
	handshake: Arc<Handshake>,
	pub peers: Arc<Peers>,
	stop_state: Arc<Mutex<StopState>>,
}

// TODO TLS
impl Server {
	/// Creates a new idle p2p server with no peers
	pub fn new(
		db_env: Arc<lmdb::Environment>,
		capab: Capabilities,
		config: P2PConfig,
		adapter: Arc<dyn ChainAdapter>,
		genesis: Hash,
		stop_state: Arc<Mutex<StopState>>,
	) -> Result<Server, Error> {
		Ok(Server {
			config: config.clone(),
			capabilities: capab,
			handshake: Arc::new(Handshake::new(genesis, config.clone())),
			peers: Arc::new(Peers::new(PeerStore::new(db_env)?, adapter, config)),
			stop_state,
		})
	}

	/// Starts a new TCP server and listen to incoming connections. This is a
	/// blocking call until the TCP server stops.
	pub fn listen(&self) -> Result<(), Error> {
		// start TCP listener and handle incoming connections
		let addr = SocketAddr::new(self.config.host, self.config.port);
		let listener = TcpListener::bind(addr)?;
		listener.set_nonblocking(true)?;

		let mut connected_sockets: HashMap<SocketAddr, TcpStream> = HashMap::new();

		let sleep_time = Duration::from_millis(1);
		loop {
			// Pause peer ingress connection request. Only for tests.
			if self.stop_state.lock().is_paused() {
				thread::sleep(Duration::from_secs(1));
				continue;
			}

			match listener.accept() {
				Ok((stream, peer_addr)) => {
					if !self.check_banned(&stream) {
						let sc = stream.try_clone();
						if let Err(e) = self.handle_new_peer(stream) {
							warn!("Error accepting peer {}: {:?}", peer_addr.to_string(), e);
						} else if let Ok(s) = sc {
							connected_sockets.insert(peer_addr, s);
						}
					}
					// if any active socket not in our peers list, close it
					self.clean_lost_sockets(&mut connected_sockets);
				}
				Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
					// nothing to do, will retry in next iteration
				}
				Err(e) => {
					warn!("Couldn't establish new client connection: {:?}", e);
				}
			}
			if self.stop_state.lock().is_stopped() {
				break;
			}
			thread::sleep(sleep_time);
		}
		Ok(())
	}

	/// Asks the server to connect to a new peer. Directly returns the peer if
	/// we're already connected to the provided address.
	pub fn connect(&self, addr: &SocketAddr) -> Result<Arc<Peer>, Error> {
		if Peer::is_denied(&self.config, &addr) {
			debug!("connect_peer: peer {} denied, not connecting.", addr);
			return Err(Error::ConnectionClose);
		}

		if global::is_production_mode() {
			let hs = self.handshake.clone();
			let addrs = hs.addrs.read();
			if addrs.contains(&addr) {
				debug!("connect: ignore connecting to PeerWithSelf, addr: {}", addr);
				return Err(Error::PeerWithSelf);
			}
		}

		if let Some(p) = self.peers.get_connected_peer(addr) {
			// if we're already connected to the addr, just return the peer
			trace!("connect_peer: already connected {}", addr);
			return Ok(p);
		}

		trace!(
			"connect_peer: on {}:{}. connecting to {}",
			self.config.host,
			self.config.port,
			addr
		);
		match TcpStream::connect_timeout(addr, Duration::from_secs(10)) {
			Ok(mut stream) => {
				let addr = SocketAddr::new(self.config.host, self.config.port);
				let total_diff = self.peers.total_difficulty();

				let mut peer = Peer::connect(
					&mut stream,
					self.capabilities,
					total_diff,
					addr,
					&self.handshake,
					self.peers.clone(),
				)?;
				peer.start(stream);
				let peer = Arc::new(peer);
				self.peers.add_connected(peer.clone())?;
				Ok(peer)
			}
			Err(e) => {
				trace!(
					"connect_peer: on {}:{}. Could not connect to {}: {:?}",
					self.config.host,
					self.config.port,
					addr,
					e
				);
				Err(Error::Connection(e))
			}
		}
	}

	fn handle_new_peer(&self, mut stream: TcpStream) -> Result<(), Error> {
		let total_diff = self.peers.total_difficulty();

		// accept the peer and add it to the server map
		let mut peer = match Peer::accept(
			&mut stream,
			self.capabilities,
			total_diff,
			&self.handshake,
			self.peers.clone(),
		) {
			Ok(p) => p,
			Err(e) => {
				// in theory, should be shutdown when stream gets dropped,
				// practically doesn't seem to be happening
				let _ = stream.shutdown(Shutdown::Both);
				return Err(e);
			}
		};
		peer.start(stream);
		self.peers.add_connected(Arc::new(peer))?;
		Ok(())
	}

	fn check_banned(&self, stream: &TcpStream) -> bool {
		// peer has been banned, go away!
		if let Ok(peer_addr) = stream.peer_addr() {
			if self.peers.is_banned(peer_addr) {
				debug!("Peer {} banned, refusing connection.", peer_addr);
				if let Err(e) = stream.shutdown(Shutdown::Both) {
					debug!("Error shutting down conn: {:?}", e);
				}
				return true;
			}
		}
		false
	}

	/// For all kinds of exception cases, the node could accepted / initiated a peer connection successfully but
	/// failed on the Handshake protocol communication, or a connected peer was closed but without a successful
	/// clean-up on its socket, that will cause this connected (on TcpStream) peer becomes so-called "invisible" peer!
	/// i.e. a peer not included in the 'self.peers.peers' hashmap. This "invisible" peer will cause some security
	/// concern because it still can send something to this node, but without enough visibility as other connected peers.
	/// Another impact is these connections could never be closed, which make the node fully occupied by all such
	/// kind of connections and become un-connectable.
	/// This function can help to clean the peer connections which is "invisible" for this node.
	fn clean_lost_sockets(&self, sockets: &mut HashMap<SocketAddr, TcpStream>) {
		let mut lost_sockets: Vec<SocketAddr> = vec![];
		for (socket, stream) in sockets.iter() {
			if !self.peers.is_known_ip(&socket) {
				if let Ok(_) = stream.shutdown(Shutdown::Both) {
					debug!(
						"clean_lost_sockets: {} cleaned which's not in peers list",
						socket
					);
				}
				lost_sockets.push(socket.clone());
			}
		}

		for socket in lost_sockets {
			sockets.remove(&socket);
		}
	}

	pub fn stop(&self) {
		self.stop_state.lock().stop();
		self.peers.stop();
	}

	/// Pause means: stop all the current peers connection, only for tests.
	/// Note:
	/// 1. must pause the 'seed' thread also, to avoid the new egress peer connection
	/// 2. must pause the 'p2p-server' thread also, to avoid the new ingress peer connection.
	pub fn pause(&self) {
		self.peers.stop();
	}
}

/// A no-op network adapter used for testing.
pub struct DummyAdapter {}

impl ChainAdapter for DummyAdapter {
	fn total_difficulty(&self) -> Difficulty {
		Difficulty::min()
	}
	fn total_height(&self) -> u64 {
		0
	}
	fn get_transaction(&self, _h: Hash) -> Option<core::Transaction> {
		None
	}
	fn tx_kernel_received(&self, _h: Hash, _addr: SocketAddr) {}
	fn transaction_received(&self, _: core::Transaction, _stem: bool) {}
	fn compact_block_received(&self, _cb: core::CompactBlock, _addr: SocketAddr) -> bool {
		true
	}
	fn header_received(&self, _bh: core::BlockHeader, _addr: SocketAddr) -> bool {
		true
	}
	fn block_received(&self, _: core::Block, _: SocketAddr) -> bool {
		true
	}
	fn headers_received(&self, _: &[core::BlockHeader], _: SocketAddr) -> bool {
		true
	}
	fn locate_headers(&self, _: &[Hash]) -> Vec<core::BlockHeader> {
		vec![]
	}
	fn get_block(&self, _: Hash) -> Option<core::Block> {
		None
	}
	fn txhashset_read(&self, _h: Hash) -> Option<TxHashSetRead> {
		unimplemented!()
	}

	fn txhashset_receive_ready(&self) -> bool {
		false
	}

	fn txhashset_write(&self, _h: Hash, _txhashset_data: File, _peer_addr: SocketAddr) -> bool {
		false
	}

	fn txhashset_download_update(
		&self,
		_start_time: DateTime<Utc>,
		_downloaded_size: u64,
		_total_size: u64,
	) -> bool {
		false
	}
}

impl NetAdapter for DummyAdapter {
	fn find_peer_addrs(&self, _: Capabilities) -> Vec<SocketAddr> {
		vec![]
	}
	fn peer_addrs_received(&self, _: Vec<SocketAddr>) {}
	fn peer_difficulty(&self, _: SocketAddr, _: Difficulty, _: u64) {}
	fn is_banned(&self, _: SocketAddr) -> bool {
		false
	}
}
<|endoftext|>


<commit_before>//! Write benchmark information to the output repository

use std::fs::{self, read_dir, File, OpenOptions};
use std::io::{BufRead, BufReader, Read, Write};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str;
use std::collections::HashSet;

use std::thread;
use std::time::{self, Instant};
use serde_json;
use collector::{ArtifactData, CommitData};
use chrono::{Duration, Utc};
use rust_sysroot::git::Commit as GitCommit;
use execute::Benchmark;
use failure::{Error, ResultExt};

pub struct Repo {
    path: PathBuf,
    use_remote: bool,
    retries: Vec<String>,
}

impl Repo {
    fn git(&self, args: &[&str]) -> Result<(), Error> {
        for iteration in 0..5 {
            let mut command = Command::new("git");
            command.current_dir(&self.path);
            info!("[{}/5]: git {:?}", iteration, args);
            command.args(args);
            let mut child = command
                .spawn()
                .with_context(|_| format!("could not spawn git {:?}", args))?;
            let start_time = Instant::now();
            loop {
                if start_time.elapsed().as_secs() > 3 {
                    warn!("killing git command -- timed out");
                    child.kill()?;
                    break;
                }
                match child.try_wait() {
                    Ok(Some(status)) => {
                        if status.success() {
                            return Ok(());
                        } else {
                            bail!(
                                "command `git {:?}` failed in `{}`",
                                args,
                                self.path.display()
                            );
                        }
                    }
                    Ok(None) => {
                        debug!("waiting 250ms...");
                        thread::sleep(time::Duration::from_millis(250));
                    },
                    Err(err) => bail!("command `git {:?}` failed to try_wait in {:?}: {:?}",
                        args, self.path.display(), err),

                }
            }
        }
        bail!("failed to run git command, timed out too many times")
    }

    pub fn open(path: PathBuf, allow_new_dir: bool, use_remote: bool) -> Result<Self, Error> {
        let mut result = Repo {
            path: path,
            use_remote,
            retries: vec![],
        };

        // Don't nuke random repositories, unless specifically requested.
        if !allow_new_dir && !result.retries_file().exists() {
            bail!("`{}` file not present", result.retries_file().display());
        }

        if result.use_remote {
            result.git(&["fetch"])?;
            result.git(&["reset", "--hard", "@{upstream}"])?;
        }

        fs::create_dir_all(result.times()).context("can't create `times/`")?;
        result.load_retries()?;

        Ok(result)
    }

    pub fn success(&self, data: &CommitData) -> Result<(), Error> {
        self.add_commit_data(data)?;
        self.commit_and_push(&format!("{} - success", data.commit.sha))?;
        Ok(())
    }

    pub fn success_artifact(&self, data: &ArtifactData) -> Result<(), Error> {
        let filepath = self.times().join(format!("artifact-{}.json", data.id));
        info!("creating file {}", filepath.display());
        let mut file = File::create(&filepath)?;
        serde_json::to_writer(&mut file, &data)?;
        self.commit_and_push(&format!("{} - success", data.id))?;
        Ok(())
    }

    pub fn find_missing_commits<'a>(
        &self,
        commits: &'a [GitCommit],
        benchmarks: &[Benchmark],
        triple: &str,
    ) -> Result<Vec<&'a GitCommit>, Error> {
        let mut have = HashSet::new();
        let path = self.times();
        for entry in read_dir(path)? {
            let entry = entry?;
            let filename = entry.file_name().to_string_lossy().to_string();
            if filename.contains("artifact") {
                continue;
            }
            let sha = if filename.contains("00:00") {
                &filename[filename.find("00:00").unwrap() + 6..filename.find("-x86").unwrap()]
            } else {
                &filename["commit-".len()..filename.find("-x86").unwrap()]
            };
            have.insert(sha.to_string());
        }

        let missing = commits
            .iter()
            .filter(|c| Utc::now().signed_duration_since(c.date) < Duration::days(29))
            .filter(|c| {
                !have.contains(&c.sha) || {
                    self.load_commit_data(c, triple)
                        .ok()
                        .map(|data| {
                            benchmarks
                                .iter()
                                .any(|b| data.benchmarks.keys().find(|k| **k == b.name).is_none())
                        })
                        .unwrap_or(true)
                }
            })
            .collect::<Vec<_>>();

        Ok(missing)
    }

    fn commit_and_push(&self, message: &str) -> Result<(), Error> {
        self.write_retries()?;
        self.git(&["add", "retries", "times"])?;

        // dirty index
        if let Err(_) = self.git(&["diff-index", "--quiet", "--cached", "HEAD"]) {
            self.git(&["commit", "-m", message])?;
            if self.use_remote {
                self.git(&["push"])?;
            }
        } else {
            println!("nothing to commit...");
        }
        Ok(())
    }

    fn load_commit_data_file(&self, filepath: &Path) -> Result<CommitData, Error> {
        trace!("loading file {}", filepath.display());
        let mut file = File::open(&filepath)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        let data = serde_json::from_str(&contents)
            .with_context(|_| format!("failed to read JSON from {:?}", filepath))?;
        Ok(data)
    }

    pub fn load_commit_data(&self, commit: &GitCommit, triple: &str) -> Result<CommitData, Error> {
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date.to_rfc3339(),
            commit.sha,
            triple
        ));
        match self.load_commit_data_file(&filepath) {
            Ok(v) => return Ok(v),
            Err(_) => {
                self.load_commit_data_file(
                    &self.times().join(format!("commit-{}-{}.json", commit.sha, triple)))
            }
        }
    }

    pub fn add_commit_data(&self, data: &CommitData) -> Result<(), Error> {
        let commit = &data.commit;
        let filepath = self.times().join(format!(
            "commit-{}-{}.json",
            commit.sha, data.triple
        ));
        info!("creating file {}", filepath.display());
        let mut file = File::create(&filepath)?;
        serde_json::to_writer(&mut file, &data)?;
        Ok(())
    }

    fn load_retries(&mut self) -> Result<(), Error> {
        let mut retries = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(self.retries_file())
            .with_context(|_| format!("can't create `{}`", self.retries_file().display()))?;
        let mut retries_s = String::new();
        retries.read_to_string(&mut retries_s)?;
        self.retries = retries_s
            .split('\n')
            .map(|line| line.trim())
            .filter(|line| !line.is_empty())
            .map(|line| {
                if line.len() == 40 {
                    Ok(line.to_owned())
                } else {
                    bail!("bad retry hash `{}`", line)
                }
            })
            .collect::<Result<_, _>>()?;
        info!("loaded retries: {:?}", self.retries);
        Ok(())
    }

    fn write_retries(&self) -> Result<(), Error> {
        info!("writing retries");
        let mut retries = OpenOptions::new()
            .write(true)
            .truncate(true)
            .open(self.retries_file())
            .context("can't create `retries`")?;
        for retry in self.retries.iter() {
            writeln!(retries, "{}", retry)?;
        }
        Ok(())
    }

    pub fn write_broken_commit(&self, commit: &GitCommit, err: Error) -> Result<(), Error> {
        info!("writing broken commit {:?}: {:?}", commit, err);
        let mut broken = OpenOptions::new()
            .write(true)
            .append(true)
            .create(true)
            .open(self.broken_commits_file())
            .context("can't create `broken-commits-log`")?;
        writeln!(broken, "{}: \"{:?}\"", commit.sha, err)?;
        Ok(())
    }

    fn broken_commits_file(&self) -> PathBuf {
        self.path.join("broken-commits-log")
    }

    fn retries_file(&self) -> PathBuf {
        self.path.join("retries")
    }

    fn times(&self) -> PathBuf {
        self.path.join("times")
    }
}
<commit_msg>Fix warnings<commit_after>//! Write benchmark information to the output repository

use std::fs::{self, read_dir, File, OpenOptions};
use std::io::{Read, Write};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str;
use std::collections::HashSet;

use std::thread;
use std::time::{self, Instant};
use serde_json;
use collector::{ArtifactData, CommitData};
use chrono::{Duration, Utc};
use rust_sysroot::git::Commit as GitCommit;
use execute::Benchmark;
use failure::{Error, ResultExt};

pub struct Repo {
    path: PathBuf,
    use_remote: bool,
    retries: Vec<String>,
}

impl Repo {
    fn git(&self, args: &[&str]) -> Result<(), Error> {
        for iteration in 0..5 {
            let mut command = Command::new("git");
            command.current_dir(&self.path);
            info!("[{}/5]: git {:?}", iteration, args);
            command.args(args);
            let mut child = command
                .spawn()
                .with_context(|_| format!("could not spawn git {:?}", args))?;
            let start_time = Instant::now();
            loop {
                if start_time.elapsed().as_secs() > 3 {
                    warn!("killing git command -- timed out");
                    child.kill()?;
                    break;
                }
                match child.try_wait() {
                    Ok(Some(status)) => {
                        if status.success() {
                            return Ok(());
                        } else {
                            bail!(
                                "command `git {:?}` failed in `{}`",
                                args,
                                self.path.display()
                            );
                        }
                    }
                    Ok(None) => {
                        debug!("waiting 250ms...");
                        thread::sleep(time::Duration::from_millis(250));
                    },
                    Err(err) => bail!("command `git {:?}` failed to try_wait in {:?}: {:?}",
                        args, self.path.display(), err),

                }
            }
        }
        bail!("failed to run git command, timed out too many times")
    }

    pub fn open(path: PathBuf, allow_new_dir: bool, use_remote: bool) -> Result<Self, Error> {
        let mut result = Repo {
            path: path,
            use_remote,
            retries: vec![],
        };

        // Don't nuke random repositories, unless specifically requested.
        if !allow_new_dir && !result.retries_file().exists() {
            bail!("`{}` file not present", result.retries_file().display());
        }

        if result.use_remote {
            result.git(&["fetch"])?;
            result.git(&["reset", "--hard", "@{upstream}"])?;
        }

        fs::create_dir_all(result.times()).context("can't create `times/`")?;
        result.load_retries()?;

        Ok(result)
    }

    pub fn success(&self, data: &CommitData) -> Result<(), Error> {
        self.add_commit_data(data)?;
        self.commit_and_push(&format!("{} - success", data.commit.sha))?;
        Ok(())
    }

    pub fn success_artifact(&self, data: &ArtifactData) -> Result<(), Error> {
        let filepath = self.times().join(format!("artifact-{}.json", data.id));
        info!("creating file {}", filepath.display());
        let mut file = File::create(&filepath)?;
        serde_json::to_writer(&mut file, &data)?;
        self.commit_and_push(&format!("{} - success", data.id))?;
        Ok(())
    }

    pub fn find_missing_commits<'a>(
        &self,
        commits: &'a [GitCommit],
        benchmarks: &[Benchmark],
        triple: &str,
    ) -> Result<Vec<&'a GitCommit>, Error> {
        let mut have = HashSet::new();
        let path = self.times();
        for entry in read_dir(path)? {
            let entry = entry?;
            let filename = entry.file_name().to_string_lossy().to_string();
            if filename.contains("artifact") {
                continue;
            }
            let sha = if filename.contains("00:00") {
                &filename[filename.find("00:00").unwrap() + 6..filename.find("-x86").unwrap()]
            } else {
                &filename["commit-".len()..filename.find("-x86").unwrap()]
            };
            have.insert(sha.to_string());
        }

        let missing = commits
            .iter()
            .filter(|c| Utc::now().signed_duration_since(c.date) < Duration::days(29))
            .filter(|c| {
                !have.contains(&c.sha) || {
                    self.load_commit_data(c, triple)
                        .ok()
                        .map(|data| {
                            benchmarks
                                .iter()
                                .any(|b| data.benchmarks.keys().find(|k| **k == b.name).is_none())
                        })
                        .unwrap_or(true)
                }
            })
            .collect::<Vec<_>>();

        Ok(missing)
    }

    fn commit_and_push(&self, message: &str) -> Result<(), Error> {
        self.write_retries()?;
        self.git(&["add", "retries", "times"])?;

        // dirty index
        if let Err(_) = self.git(&["diff-index", "--quiet", "--cached", "HEAD"]) {
            self.git(&["commit", "-m", message])?;
            if self.use_remote {
                self.git(&["push"])?;
            }
        } else {
            println!("nothing to commit...");
        }
        Ok(())
    }

    fn load_commit_data_file(&self, filepath: &Path) -> Result<CommitData, Error> {
        trace!("loading file {}", filepath.display());
        let mut file = File::open(&filepath)?;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        let data = serde_json::from_str(&contents)
            .with_context(|_| format!("failed to read JSON from {:?}", filepath))?;
        Ok(data)
    }

    pub fn load_commit_data(&self, commit: &GitCommit, triple: &str) -> Result<CommitData, Error> {
        let filepath = self.times().join(format!(
            "{}-{}-{}.json",
            commit.date.to_rfc3339(),
            commit.sha,
            triple
        ));
        match self.load_commit_data_file(&filepath) {
            Ok(v) => return Ok(v),
            Err(_) => {
                self.load_commit_data_file(
                    &self.times().join(format!("commit-{}-{}.json", commit.sha, triple)))
            }
        }
    }

    pub fn add_commit_data(&self, data: &CommitData) -> Result<(), Error> {
        let commit = &data.commit;
        let filepath = self.times().join(format!(
            "commit-{}-{}.json",
            commit.sha, data.triple
        ));
        info!("creating file {}", filepath.display());
        let mut file = File::create(&filepath)?;
        serde_json::to_writer(&mut file, &data)?;
        Ok(())
    }

    fn load_retries(&mut self) -> Result<(), Error> {
        let mut retries = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(self.retries_file())
            .with_context(|_| format!("can't create `{}`", self.retries_file().display()))?;
        let mut retries_s = String::new();
        retries.read_to_string(&mut retries_s)?;
        self.retries = retries_s
            .split('\n')
            .map(|line| line.trim())
            .filter(|line| !line.is_empty())
            .map(|line| {
                if line.len() == 40 {
                    Ok(line.to_owned())
                } else {
                    bail!("bad retry hash `{}`", line)
                }
            })
            .collect::<Result<_, _>>()?;
        info!("loaded retries: {:?}", self.retries);
        Ok(())
    }

    fn write_retries(&self) -> Result<(), Error> {
        info!("writing retries");
        let mut retries = OpenOptions::new()
            .write(true)
            .truncate(true)
            .open(self.retries_file())
            .context("can't create `retries`")?;
        for retry in self.retries.iter() {
            writeln!(retries, "{}", retry)?;
        }
        Ok(())
    }

    pub fn write_broken_commit(&self, commit: &GitCommit, err: Error) -> Result<(), Error> {
        info!("writing broken commit {:?}: {:?}", commit, err);
        let mut broken = OpenOptions::new()
            .write(true)
            .append(true)
            .create(true)
            .open(self.broken_commits_file())
            .context("can't create `broken-commits-log`")?;
        writeln!(broken, "{}: \"{:?}\"", commit.sha, err)?;
        Ok(())
    }

    fn broken_commits_file(&self) -> PathBuf {
        self.path.join("broken-commits-log")
    }

    fn retries_file(&self) -> PathBuf {
        self.path.join("retries")
    }

    fn times(&self) -> PathBuf {
        self.path.join("times")
    }
}
<|endoftext|>


<commit_before>#![allow(mutable_borrow_reservation_conflict)]

trait S: Sized {
    fn tpb(&mut self, _s: Self) {}
}

impl S for i32 {}

fn two_phase1() {
    let mut x = 3;
    x.tpb(x);
}

fn two_phase2() {
    let mut v = vec![];
    v.push(v.len());
}

fn two_phase3(b: bool) {
    let mut x = &mut vec![];
    let mut y = vec![];
    x.push((
        {
            if b { x = &mut y };
            22
        },
        x.len(),
    ));
}

#[allow(unreachable_code)]
fn two_phase_raw() {
    let x: &mut Vec<i32> = &mut vec![];
    x.push(
        {
            // Unfortunately this does not trigger the problem of creating a
            // raw ponter from a pointer that had a two-phase borrow derived from
            // it because of the implicit &mut reborrow.
            let raw = x as *mut _;
            unsafe { *raw = vec![1]; }
            return
        }
    );
}

fn two_phase_overlapping1() {
    let mut x = vec![];
    let p = &x;
    x.push(p.len());
}

fn two_phase_overlapping2() {
    use std::ops::AddAssign;
    let mut x = 1;
    let l = &x;
    x.add_assign(x + *l);
}

fn with_interior_mutability() {
    use std::cell::Cell;

    trait Thing: Sized {
        fn do_the_thing(&mut self, _s: i32) {}
    }

    impl<T> Thing for Cell<T> {}

    let mut x = Cell::new(1);
    let l = &x;

    x
        .do_the_thing({
            x.set(3);
            l.set(4);
            x.get() + l.get()
        })
    ;
}

fn main() {
    two_phase1();
    two_phase2();
    two_phase3(false);
    two_phase3(true);
    two_phase_raw();
    with_interior_mutability();
    two_phase_overlapping1();
    two_phase_overlapping2();
}
<commit_msg>make sure 2-phase borows work even with raw ptr tagging<commit_after>// compile-flags: -Zmiri-tag-raw-pointers
#![allow(mutable_borrow_reservation_conflict)]

trait S: Sized {
    fn tpb(&mut self, _s: Self) {}
}

impl S for i32 {}

fn two_phase1() {
    let mut x = 3;
    x.tpb(x);
}

fn two_phase2() {
    let mut v = vec![];
    v.push(v.len());
}

fn two_phase3(b: bool) {
    let mut x = &mut vec![];
    let mut y = vec![];
    x.push((
        {
            if b { x = &mut y };
            22
        },
        x.len(),
    ));
}

#[allow(unreachable_code)]
fn two_phase_raw() {
    let x: &mut Vec<i32> = &mut vec![];
    x.push(
        {
            // Unfortunately this does not trigger the problem of creating a
            // raw ponter from a pointer that had a two-phase borrow derived from
            // it because of the implicit &mut reborrow.
            let raw = x as *mut _;
            unsafe { *raw = vec![1]; }
            return
        }
    );
}

fn two_phase_overlapping1() {
    let mut x = vec![];
    let p = &x;
    x.push(p.len());
}

fn two_phase_overlapping2() {
    use std::ops::AddAssign;
    let mut x = 1;
    let l = &x;
    x.add_assign(x + *l);
}

fn with_interior_mutability() {
    use std::cell::Cell;

    trait Thing: Sized {
        fn do_the_thing(&mut self, _s: i32) {}
    }

    impl<T> Thing for Cell<T> {}

    let mut x = Cell::new(1);
    let l = &x;

    x
        .do_the_thing({
            x.set(3);
            l.set(4);
            x.get() + l.get()
        })
    ;
}

fn main() {
    two_phase1();
    two_phase2();
    two_phase3(false);
    two_phase3(true);
    two_phase_raw();
    with_interior_mutability();
    two_phase_overlapping1();
    two_phase_overlapping2();
}
<|endoftext|>