<commit_before>pub mod mut_message_client;

use std::env;
use std::io::*;
use std::mem;
use std::net::*;
use std::panic::{catch_unwind, UnwindSafe};
use std::process::{Command, Stdio};
use std::str::FromStr;
use std::sync::*;
use std::thread;
use std::time::*;

use tokio::runtime::current_thread::Runtime;

use trust_dns_proto::xfer::DnsResponse;

use trust_dns::client::*;
use trust_dns::rr::dnssec::*;
use trust_dns::rr::rdata::{DNSSECRData, DNSSECRecordType};
use trust_dns::rr::*;

use self::mut_message_client::MutMessageHandle;

/// Spins up a Server and handles shutting it down after running the test
#[allow(dead_code)]
pub fn named_test_harness<F, R>(toml: &str, test: F)
where
    F: FnOnce(u16, u16) -> R + UnwindSafe,
{
    // find a random port to listen on
    let (test_port, test_tls_port) = {
        let server = UdpSocket::bind(("0.0.0.0", 0)).unwrap();
        let server_addr = server.local_addr().unwrap();
        let test_port = server_addr.port();

        let server = UdpSocket::bind(("0.0.0.0", 0)).unwrap();
        let server_addr = server.local_addr().unwrap();
        let test_tls_port = server_addr.port();

        assert!(test_port != test_tls_port);
        (test_port, test_tls_port)
    };

    let server_path = env::var("TDNS_SERVER_SRC_ROOT").unwrap_or_else(|_| ".".to_owned());
    println!("using server src path: {}", server_path);

    let mut named = Command::new(&format!("{}/../target/debug/named", server_path))
        .stdout(Stdio::piped())
        .arg("-d")
        .arg(&format!(
            "--config={}/tests/named_test_configs/{}",
            server_path, toml
        ))
        .arg(&format!(
            "--zonedir={}/tests/named_test_configs",
            server_path
        ))
        .arg(&format!("--port={}", test_port))
        .arg(&format!("--tls-port={}", test_tls_port))
        .spawn()
        .expect("failed to start named");

    let mut named_out = BufReader::new(mem::replace(&mut named.stdout, None).expect("no stdout"));

    // forced thread killer
    let named = Arc::new(Mutex::new(named));
    let named_killer = Arc::clone(&named);
    let succeeded = Arc::new(atomic::AtomicBool::new(false));
    let succeeded_clone = succeeded.clone();
    let killer_join = thread::Builder::new()
        .name("thread_killer".to_string())
        .spawn(move || {
            let succeeded = succeeded_clone;

            let kill_named = || {
                println!("killing named");

                let mut named = named_killer.lock().unwrap();
                if let Err(e) = named.kill() {
                    println!("warning: failed to kill named: {:?}", e);
                }
            };

            for _ in 0..30 {
                thread::sleep(Duration::from_secs(1));
                if succeeded.load(atomic::Ordering::Relaxed) {
                    kill_named();
                    return;
                }
            }

            kill_named();
            panic!("timeout");
        })
        .expect("could not start thread killer");

    // we should get the correct output before 1000 lines...
    let mut output = String::new();
    let mut found = false;
    for _ in 0..10_000 {
        {
            assert!(
                named
                    .lock()
                    .unwrap()
                    .try_wait()
                    .expect("failed to check status of named")
                    .is_none(),
                "named has already exited"
            );
        }

        output.clear();
        named_out
            .read_line(&mut output)
            .expect("could not read stdout");
        if !output.is_empty() {
            stdout().write_all(b"SRV: ").unwrap();
            stdout().write_all(output.as_bytes()).unwrap();
        }
        if output.contains("awaiting connections...") {
            found = true;
            break;
        }
    }

    stdout().flush().unwrap();
    assert!(found);

    // spawn a thread to capture stdout
    let succeeded_clone = succeeded.clone();
    thread::Builder::new()
        .name("named stdout".into())
        .spawn(move || {
            let succeeded = succeeded_clone;
            while !succeeded.load(atomic::Ordering::Relaxed) {
                output.clear();
                named_out
                    .read_line(&mut output)
                    .expect("could not read stdout");
                if !output.is_empty() {
                    stdout().write_all(b"SRV: ").unwrap();
                    stdout().write_all(output.as_bytes()).unwrap();
                }
            }
        })
        .expect("no thread available");

    println!("running test...");

    let result = catch_unwind(move || test(test_port, test_tls_port));

    println!("test completed");
    succeeded.store(true, atomic::Ordering::Relaxed);
    killer_join.join().expect("join failed");

    assert!(result.is_ok(), "test failed");
}

pub fn query_message<C: ClientHandle>(
    io_loop: &mut Runtime,
    client: &mut C,
    name: Name,
    record_type: RecordType,
) -> DnsResponse {
    println!("sending request");
    let response = io_loop.block_on(client.query(name.clone(), DNSClass::IN, record_type));
    println!("got response: {:#?}", response);
    response.expect("request failed")
}

// This only validates that a query to the server works, it shouldn't be used for more than this.
//  i.e. more complex checks live with the clients and authorities to validate deeper funcionality
#[allow(dead_code)]
pub fn query_a<C: ClientHandle>(io_loop: &mut Runtime, client: &mut C) {
    let name = Name::from_str("www.example.com").unwrap();
    let response = query_message(io_loop, client, name, RecordType::A);
    let record = &response.answers()[0];

    if let RData::A(ref address) = *record.rdata() {
        assert!(address == &Ipv4Addr::new(127, 0, 0, 1))
    } else {
        panic!("wrong RDATA")
    }
}

// This only validates that a query to the server works, it shouldn't be used for more than this.
//  i.e. more complex checks live with the clients and authorities to validate deeper funcionality
#[allow(dead_code)]
pub fn query_all_dnssec(
    io_loop: &mut Runtime,
    client: BasicClientHandle,
    algorithm: Algorithm,
    with_rfc6975: bool,
) {
    let name = Name::from_str("example.com.").unwrap();
    let mut client = MutMessageHandle::new(client);
    client.dnssec_ok = true;
    if with_rfc6975 {
        client.support_algorithms = Some(SupportedAlgorithms::from_vec(&[algorithm]));
    }

    let response = query_message(
        io_loop,
        &mut client,
        name,
        RecordType::DNSSEC(DNSSECRecordType::DNSKEY),
    );

    let dnskey = response
        .answers()
        .iter()
        .filter(|r| r.rr_type() == RecordType::DNSSEC(DNSSECRecordType::DNSKEY))
        .map(|r| {
            if let RData::DNSSEC(DNSSECRData::DNSKEY(ref dnskey)) = *r.rdata() {
                dnskey.clone()
            } else {
                panic!("wrong RDATA")
            }
        })
        .find(|d| d.algorithm() == algorithm);
    assert!(dnskey.is_some(), "DNSKEY not found");

    let rrsig = response
        .answers()
        .iter()
        .filter(|r| r.rr_type() == RecordType::DNSSEC(DNSSECRecordType::RRSIG))
        .map(|r| {
            if let RData::DNSSEC(DNSSECRData::SIG(ref rrsig)) = *r.rdata() {
                rrsig.clone()
            } else {
                panic!("wrong RDATA")
            }
        })
        .filter(|rrsig| rrsig.algorithm() == algorithm)
        .find(|rrsig| rrsig.type_covered() == RecordType::DNSSEC(DNSSECRecordType::DNSKEY));
    assert!(rrsig.is_some(), "Associated RRSIG not found");
}

#[allow(dead_code)]
pub fn query_all_dnssec_with_rfc6975(
    io_loop: &mut Runtime,
    client: BasicClientHandle,
    algorithm: Algorithm,
) {
    query_all_dnssec(io_loop, client, algorithm, true)
}

#[allow(dead_code)]
pub fn query_all_dnssec_wo_rfc6975(
    io_loop: &mut Runtime,
    client: BasicClientHandle,
    algorithm: Algorithm,
) {
    query_all_dnssec(io_loop, client, algorithm, false)
}
<commit_msg>use time rather than number of lines for exit<commit_after>pub mod mut_message_client;

use std::env;
use std::io::*;
use std::mem;
use std::net::*;
use std::panic::{catch_unwind, UnwindSafe};
use std::process::{Command, Stdio};
use std::str::FromStr;
use std::sync::*;
use std::thread;
use std::time::*;

use tokio::runtime::current_thread::Runtime;

use trust_dns_proto::xfer::DnsResponse;

use trust_dns::client::*;
use trust_dns::rr::dnssec::*;
use trust_dns::rr::rdata::{DNSSECRData, DNSSECRecordType};
use trust_dns::rr::*;

use self::mut_message_client::MutMessageHandle;

/// Spins up a Server and handles shutting it down after running the test
#[allow(dead_code)]
pub fn named_test_harness<F, R>(toml: &str, test: F)
where
    F: FnOnce(u16, u16) -> R + UnwindSafe,
{
    // find a random port to listen on
    let (test_port, test_tls_port) = {
        let server = UdpSocket::bind(("0.0.0.0", 0)).unwrap();
        let server_addr = server.local_addr().unwrap();
        let test_port = server_addr.port();

        let server = UdpSocket::bind(("0.0.0.0", 0)).unwrap();
        let server_addr = server.local_addr().unwrap();
        let test_tls_port = server_addr.port();

        assert!(test_port != test_tls_port);
        (test_port, test_tls_port)
    };

    let server_path = env::var("TDNS_SERVER_SRC_ROOT").unwrap_or_else(|_| ".".to_owned());
    println!("using server src path: {}", server_path);

    let mut named = Command::new(&format!("{}/../target/debug/named", server_path))
        .stdout(Stdio::piped())
        .arg("-d")
        .arg(&format!(
            "--config={}/tests/named_test_configs/{}",
            server_path, toml
        ))
        .arg(&format!(
            "--zonedir={}/tests/named_test_configs",
            server_path
        ))
        .arg(&format!("--port={}", test_port))
        .arg(&format!("--tls-port={}", test_tls_port))
        .spawn()
        .expect("failed to start named");

    let mut named_out = BufReader::new(mem::replace(&mut named.stdout, None).expect("no stdout"));

    // forced thread killer
    let named = Arc::new(Mutex::new(named));
    let named_killer = Arc::clone(&named);
    let succeeded = Arc::new(atomic::AtomicBool::new(false));
    let succeeded_clone = succeeded.clone();
    let killer_join = thread::Builder::new()
        .name("thread_killer".to_string())
        .spawn(move || {
            let succeeded = succeeded_clone;

            let kill_named = || {
                println!("killing named");

                let mut named = named_killer.lock().unwrap();
                if let Err(e) = named.kill() {
                    println!("warning: failed to kill named: {:?}", e);
                }
            };

            for _ in 0..30 {
                thread::sleep(Duration::from_secs(1));
                if succeeded.load(atomic::Ordering::Relaxed) {
                    kill_named();
                    return;
                }
            }

            kill_named();
            panic!("timeout");
        })
        .expect("could not start thread killer");

    // we should get the correct output before 1000 lines...
    let mut output = String::new();
    let mut found = false;
    let wait_for_start_until = Instant::now() + Duration::from_secs(60);

    while Instant::now() < wait_for_start_until {
        {
            assert!(
                named
                    .lock()
                    .unwrap()
                    .try_wait()
                    .expect("failed to check status of named")
                    .is_none(),
                "named has already exited"
            );
        }

        output.clear();
        named_out
            .read_line(&mut output)
            .expect("could not read stdout");
        if !output.is_empty() {
            stdout().write_all(b"SRV: ").unwrap();
            stdout().write_all(output.as_bytes()).unwrap();
        }
        if output.contains("awaiting connections...") {
            found = true;
            break;
        }
    }

    stdout().flush().unwrap();
    assert!(found);

    // spawn a thread to capture stdout
    let succeeded_clone = succeeded.clone();
    thread::Builder::new()
        .name("named stdout".into())
        .spawn(move || {
            let succeeded = succeeded_clone;
            while !succeeded.load(atomic::Ordering::Relaxed) {
                output.clear();
                named_out
                    .read_line(&mut output)
                    .expect("could not read stdout");
                if !output.is_empty() {
                    stdout().write_all(b"SRV: ").unwrap();
                    stdout().write_all(output.as_bytes()).unwrap();
                }
            }
        })
        .expect("no thread available");

    println!("running test...");

    let result = catch_unwind(move || test(test_port, test_tls_port));

    println!("test completed");
    succeeded.store(true, atomic::Ordering::Relaxed);
    killer_join.join().expect("join failed");

    assert!(result.is_ok(), "test failed");
}

pub fn query_message<C: ClientHandle>(
    io_loop: &mut Runtime,
    client: &mut C,
    name: Name,
    record_type: RecordType,
) -> DnsResponse {
    println!("sending request");
    let response = io_loop.block_on(client.query(name.clone(), DNSClass::IN, record_type));
    println!("got response: {:#?}", response);
    response.expect("request failed")
}

// This only validates that a query to the server works, it shouldn't be used for more than this.
//  i.e. more complex checks live with the clients and authorities to validate deeper funcionality
#[allow(dead_code)]
pub fn query_a<C: ClientHandle>(io_loop: &mut Runtime, client: &mut C) {
    let name = Name::from_str("www.example.com").unwrap();
    let response = query_message(io_loop, client, name, RecordType::A);
    let record = &response.answers()[0];

    if let RData::A(ref address) = *record.rdata() {
        assert!(address == &Ipv4Addr::new(127, 0, 0, 1))
    } else {
        panic!("wrong RDATA")
    }
}

// This only validates that a query to the server works, it shouldn't be used for more than this.
//  i.e. more complex checks live with the clients and authorities to validate deeper funcionality
#[allow(dead_code)]
pub fn query_all_dnssec(
    io_loop: &mut Runtime,
    client: BasicClientHandle,
    algorithm: Algorithm,
    with_rfc6975: bool,
) {
    let name = Name::from_str("example.com.").unwrap();
    let mut client = MutMessageHandle::new(client);
    client.dnssec_ok = true;
    if with_rfc6975 {
        client.support_algorithms = Some(SupportedAlgorithms::from_vec(&[algorithm]));
    }

    let response = query_message(
        io_loop,
        &mut client,
        name,
        RecordType::DNSSEC(DNSSECRecordType::DNSKEY),
    );

    let dnskey = response
        .answers()
        .iter()
        .filter(|r| r.rr_type() == RecordType::DNSSEC(DNSSECRecordType::DNSKEY))
        .map(|r| {
            if let RData::DNSSEC(DNSSECRData::DNSKEY(ref dnskey)) = *r.rdata() {
                dnskey.clone()
            } else {
                panic!("wrong RDATA")
            }
        })
        .find(|d| d.algorithm() == algorithm);
    assert!(dnskey.is_some(), "DNSKEY not found");

    let rrsig = response
        .answers()
        .iter()
        .filter(|r| r.rr_type() == RecordType::DNSSEC(DNSSECRecordType::RRSIG))
        .map(|r| {
            if let RData::DNSSEC(DNSSECRData::SIG(ref rrsig)) = *r.rdata() {
                rrsig.clone()
            } else {
                panic!("wrong RDATA")
            }
        })
        .filter(|rrsig| rrsig.algorithm() == algorithm)
        .find(|rrsig| rrsig.type_covered() == RecordType::DNSSEC(DNSSECRecordType::DNSKEY));
    assert!(rrsig.is_some(), "Associated RRSIG not found");
}

#[allow(dead_code)]
pub fn query_all_dnssec_with_rfc6975(
    io_loop: &mut Runtime,
    client: BasicClientHandle,
    algorithm: Algorithm,
) {
    query_all_dnssec(io_loop, client, algorithm, true)
}

#[allow(dead_code)]
pub fn query_all_dnssec_wo_rfc6975(
    io_loop: &mut Runtime,
    client: BasicClientHandle,
    algorithm: Algorithm,
) {
    query_all_dnssec(io_loop, client, algorithm, false)
}
<|endoftext|>


<commit_before>#![feature(const_fn, proc_macro)]

extern crate mocktopus;

mod mocking_fns;
mod mocking_methods;
mod mocking_trait_defaults;
mod mocking_traits;

use mocktopus::macros::*;
use mocktopus::mocking::*;
use mocktopus::mocking_utils::*;
#[allow(unused_imports)] //Linter error
use std::ascii::AsciiExt;
use std::fmt::Display;

mod mock_safe {
    use super::*;

    #[mockable]
    pub fn no_args_returns_str() -> &'static str {
        "not mocked"
    }

    #[test]
    fn when_not_mocked_then_returns_not_mocked() {
        assert_eq!("not mocked", no_args_returns_str());
    }

    #[test]
    fn when_mocked_then_returns_mocked() {
        no_args_returns_str.mock_safe(|| MockResult::Return("mocked"));

        assert_eq!("mocked", no_args_returns_str());
    }
}

mod mocks_do_not_leak_between_tests {
    use super::*;

    #[mockable]
    pub fn no_args_returns_str() -> &'static str {
        "not mocked"
    }

    macro_rules! generate_tests {
        ($($fn_name:ident),+) => {
            $(
                #[test]
                fn $fn_name() {
                    assert_eq!("not mocked", no_args_returns_str(), "function was mocked before mocking");

                    unsafe {
                        no_args_returns_str.mock_raw(|| MockResult::Return((stringify!($fn_name))));
                    }

                    assert_eq!(stringify!($fn_name), no_args_returns_str(), "mocking failed");
                }
            )+
        }
    }

    generate_tests!(t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19);
    generate_tests!(t20, t21, t22, t23, t24, t25, t26, t27, t28, t29, t30, t31, t32, t33, t34, t35, t36, t37, t38, t39);
    generate_tests!(t40, t41, t42, t43, t44, t45, t46, t47, t48, t49, t50, t51, t52, t53, t54, t55, t56, t57, t58, t59);
    generate_tests!(t60, t61, t62, t63, t64, t65, t66, t67, t68, t69, t70, t71, t72, t73, t74, t75, t76, t77, t78, t79);
    generate_tests!(t80, t81, t82, t83, t84, t85, t86, t87, t88, t89, t90, t91, t92, t93, t94, t95, t96, t97, t98, t99);
}

mod panicking_inside_mock_is_safe {
    use super::*;

    #[mockable]
    fn function(_has_drop: String) {

    }

    #[test]
    #[should_panic]
    fn uninitialised_string_is_not_dropped() {
        function.mock_safe(|_| panic!("inside mock"));

        function("initialised".to_string());
    }
}

mod mocking_generic_over_a_type_with_lifetime_mocks_all_lifetime_variants {
    use super::*;
    use std::fmt::Display;

    #[mockable]
    fn function<T: Display>(generic: T) -> String {
        format!("not mocked {}", generic)
    }

    static STATIC_CHAR: char = 'S';

    #[test]
    fn all_lifetime_variants_get_mocked() {
        unsafe {
            function::<&char>.mock_raw(|c| MockResult::Return(format!("mocked {}", c)));
        }
        let local_char = 'L';

        assert_eq!("mocked L", function(&local_char));
        assert_eq!("mocked S", function(&STATIC_CHAR));
        assert_eq!("not mocked 3", function(&3));
    }
}

mod mocking_generic_over_a_reference_does_not_mock_opposite_mutability_variant {
    use super::*;
    use std::fmt::Display;

    #[mockable]
    fn function<T: Display>(generic: T) -> String {
        format!("not mocked {}", generic)
    }

    #[test]
    fn mocking_for_ref_does_not_mock_for_mut_ref() {
        unsafe {
            function::<&char>.mock_raw(|c| MockResult::Return(format!("mocked {}", c)));
        }

        assert_eq!("mocked R", function(&'R'));
        assert_eq!("not mocked M", function(&mut 'M'));
    }

    #[test]
    fn mocking_for_mut_ref_does_not_mock_for_ref() {
        unsafe {
            function::<&mut char>.mock_raw(|c| MockResult::Return(format!("mocked {}", c)));
        }

        assert_eq!("not mocked R", function(&'R'));
        assert_eq!("mocked M", function(&mut 'M'));
    }
}

mod mocking_trait_default_for_struct_does_not_mock_same_default_for_another_struct {
    use super::*;

    #[mockable]
    trait Trait {
        fn function() -> &'static str {
            "not mocked"
        }
    }

    struct Struct1;

    impl Trait for Struct1 {

    }

    struct Struct2;

    impl Trait for Struct2 {

    }

    #[test]
    fn when_not_mocked_then_both_run_normally() {
        assert_eq!("not mocked", Struct1::function());
        assert_eq!("not mocked", Struct2::function());
    }

    #[test]
    fn when_mocked_for_one_then_runs_mock_for_it_and_runs_normally_for_other() {
        unsafe {
            Struct1::function.mock_raw(|| MockResult::Return("mocked"))
        }

        assert_eq!("mocked", Struct1::function());
        assert_eq!("not mocked", Struct2::function());
    }
}
<commit_msg>Fix warnings in tests<commit_after>#![feature(const_fn, proc_macro)]

extern crate mocktopus;

mod mocking_fns;
mod mocking_methods;
mod mocking_trait_defaults;
mod mocking_traits;

use mocktopus::macros::*;
use mocktopus::mocking::*;
use mocktopus::mocking_utils::*;
#[allow(unused_imports)] //Linter error
use std::ascii::AsciiExt;
use std::fmt::Display;

mod mock_safe {
    use super::*;

    #[mockable]
    pub fn no_args_returns_str() -> &'static str {
        "not mocked"
    }

    #[test]
    fn when_not_mocked_then_returns_not_mocked() {
        assert_eq!("not mocked", no_args_returns_str());
    }

    #[test]
    fn when_mocked_then_returns_mocked() {
        no_args_returns_str.mock_safe(|| MockResult::Return("mocked"));

        assert_eq!("mocked", no_args_returns_str());
    }
}

mod mocks_do_not_leak_between_tests {
    use super::*;

    #[mockable]
    pub fn no_args_returns_str() -> &'static str {
        "not mocked"
    }

    macro_rules! generate_tests {
        ($($fn_name:ident),+) => {
            $(
                #[test]
                fn $fn_name() {
                    assert_eq!("not mocked", no_args_returns_str(), "function was mocked before mocking");

                    unsafe {
                        no_args_returns_str.mock_raw(|| MockResult::Return(stringify!($fn_name)));
                    }

                    assert_eq!(stringify!($fn_name), no_args_returns_str(), "mocking failed");
                }
            )+
        }
    }

    generate_tests!(t00, t01, t02, t03, t04, t05, t06, t07, t08, t09, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19);
    generate_tests!(t20, t21, t22, t23, t24, t25, t26, t27, t28, t29, t30, t31, t32, t33, t34, t35, t36, t37, t38, t39);
    generate_tests!(t40, t41, t42, t43, t44, t45, t46, t47, t48, t49, t50, t51, t52, t53, t54, t55, t56, t57, t58, t59);
    generate_tests!(t60, t61, t62, t63, t64, t65, t66, t67, t68, t69, t70, t71, t72, t73, t74, t75, t76, t77, t78, t79);
    generate_tests!(t80, t81, t82, t83, t84, t85, t86, t87, t88, t89, t90, t91, t92, t93, t94, t95, t96, t97, t98, t99);
}

mod panicking_inside_mock_is_safe {
    use super::*;

    #[mockable]
    fn function(_has_drop: String) {

    }

    #[test]
    #[should_panic]
    fn uninitialised_string_is_not_dropped() {
        function.mock_safe(|_| panic!("inside mock"));

        function("initialised".to_string());
    }
}

mod mocking_generic_over_a_type_with_lifetime_mocks_all_lifetime_variants {
    use super::*;
    use std::fmt::Display;

    #[mockable]
    fn function<T: Display>(generic: T) -> String {
        format!("not mocked {}", generic)
    }

    static STATIC_CHAR: char = 'S';

    #[test]
    fn all_lifetime_variants_get_mocked() {
        unsafe {
            function::<&char>.mock_raw(|c| MockResult::Return(format!("mocked {}", c)));
        }
        let local_char = 'L';

        assert_eq!("mocked L", function(&local_char));
        assert_eq!("mocked S", function(&STATIC_CHAR));
        assert_eq!("not mocked 3", function(&3));
    }
}

mod mocking_generic_over_a_reference_does_not_mock_opposite_mutability_variant {
    use super::*;
    use std::fmt::Display;

    #[mockable]
    fn function<T: Display>(generic: T) -> String {
        format!("not mocked {}", generic)
    }

    #[test]
    fn mocking_for_ref_does_not_mock_for_mut_ref() {
        unsafe {
            function::<&char>.mock_raw(|c| MockResult::Return(format!("mocked {}", c)));
        }

        assert_eq!("mocked R", function(&'R'));
        assert_eq!("not mocked M", function(&mut 'M'));
    }

    #[test]
    fn mocking_for_mut_ref_does_not_mock_for_ref() {
        unsafe {
            function::<&mut char>.mock_raw(|c| MockResult::Return(format!("mocked {}", c)));
        }

        assert_eq!("not mocked R", function(&'R'));
        assert_eq!("mocked M", function(&mut 'M'));
    }
}

mod mocking_trait_default_for_struct_does_not_mock_same_default_for_another_struct {
    use super::*;

    #[mockable]
    trait Trait {
        fn function() -> &'static str {
            "not mocked"
        }
    }

    struct Struct1;

    impl Trait for Struct1 {

    }

    struct Struct2;

    impl Trait for Struct2 {

    }

    #[test]
    fn when_not_mocked_then_both_run_normally() {
        assert_eq!("not mocked", Struct1::function());
        assert_eq!("not mocked", Struct2::function());
    }

    #[test]
    fn when_mocked_for_one_then_runs_mock_for_it_and_runs_normally_for_other() {
        unsafe {
            Struct1::function.mock_raw(|| MockResult::Return("mocked"))
        }

        assert_eq!("mocked", Struct1::function());
        assert_eq!("not mocked", Struct2::function());
    }
}
<|endoftext|>


<commit_before>//! Sanity check that alternate hashers work correctly.

use hashbrown::HashSet;
use std::hash::{BuildHasher, BuildHasherDefault, Hasher};

fn check<S: BuildHasher + Default>() {
    let range = 0..1_000;

    let mut set = HashSet::<i32, S>::default();
    set.extend(range.clone());

    assert!(!set.contains(&i32::min_value()));
    assert!(!set.contains(&(range.start - 1)));
    for i in range.clone() {
        assert!(set.contains(&i));
    }
    assert!(!set.contains(&range.end));
    assert!(!set.contains(&i32::max_value()));
}

/// Use hashbrown's default hasher.
#[test]
fn default() {
    check::<hashbrown::hash_map::DefaultHashBuilder>();
}

/// Use std's default hasher.
#[test]
fn random_state() {
    check::<std::collections::hash_map::RandomState>();
}

/// Use a constant 0 hash.
#[test]
fn zero() {
    #[derive(Default)]
    struct ZeroHasher;

    impl Hasher for ZeroHasher {
        fn finish(&self) -> u64 {
            0
        }
        fn write(&mut self, _: &[u8]) {}
    }

    check::<BuildHasherDefault<ZeroHasher>>();
}

/// Use a constant maximum hash.
#[test]
fn max() {
    #[derive(Default)]
    struct MaxHasher;

    impl Hasher for MaxHasher {
        fn finish(&self) -> u64 {
            u64::max_value()
        }
        fn write(&mut self, _: &[u8]) {}
    }

    check::<BuildHasherDefault<MaxHasher>>();
}
<commit_msg>Exclude miri from tests/hasher.rs<commit_after>//! Sanity check that alternate hashers work correctly.

#![cfg(not(miri))] // FIXME: takes too long

use hashbrown::HashSet;
use std::hash::{BuildHasher, BuildHasherDefault, Hasher};

fn check<S: BuildHasher + Default>() {
    let range = 0..1_000;

    let mut set = HashSet::<i32, S>::default();
    set.extend(range.clone());

    assert!(!set.contains(&i32::min_value()));
    assert!(!set.contains(&(range.start - 1)));
    for i in range.clone() {
        assert!(set.contains(&i));
    }
    assert!(!set.contains(&range.end));
    assert!(!set.contains(&i32::max_value()));
}

/// Use hashbrown's default hasher.
#[test]
fn default() {
    check::<hashbrown::hash_map::DefaultHashBuilder>();
}

/// Use std's default hasher.
#[test]
fn random_state() {
    check::<std::collections::hash_map::RandomState>();
}

/// Use a constant 0 hash.
#[test]
fn zero() {
    #[derive(Default)]
    struct ZeroHasher;

    impl Hasher for ZeroHasher {
        fn finish(&self) -> u64 {
            0
        }
        fn write(&mut self, _: &[u8]) {}
    }

    check::<BuildHasherDefault<ZeroHasher>>();
}

/// Use a constant maximum hash.
#[test]
fn max() {
    #[derive(Default)]
    struct MaxHasher;

    impl Hasher for MaxHasher {
        fn finish(&self) -> u64 {
            u64::max_value()
        }
        fn write(&mut self, _: &[u8]) {}
    }

    check::<BuildHasherDefault<MaxHasher>>();
}
<|endoftext|>


<commit_before>extern crate support;
extern crate futures;

use futures::{failed, finished, Future};
use futures::stream::*;
use support::*;

// #[test]
// fn smoke() {
//     let (tx, rx) = channel::<i32, u32>();
//     tx.send(Ok(1))
//       .and_then(|tx| tx.send(Ok(2)))
//       .and_then(|tx| tx.send(Ok(3)))
//       .schedule(|r| assert!(r.is_ok()));
//     assert_eq!(rx.collect(), Ok(vec![1, 2, 3]));
//
//     let (tx, rx) = channel::<i32, u32>();
//     tx.send(Ok(1))
//       .and_then(|tx| tx.send(Err(2)))
//       .and_then(|tx| tx.send(Ok(3)))
//       .schedule(|r| assert!(r.is_ok()));
//     assert_eq!(rx.collect(), Err(2));
// }

fn list() -> Receiver<i32, u32> {
    let (tx, rx) = channel();
    tx.send(Ok(1))
      .and_then(|tx| tx.send(Ok(2)))
      .and_then(|tx| tx.send(Ok(3)))
      .forget();
    return rx
}

fn err_list() -> Receiver<i32, u32> {
    let (tx, rx) = channel();
    tx.send(Ok(1))
      .and_then(|tx| tx.send(Ok(2)))
      .and_then(|tx| tx.send(Err(3)))
      .forget();
    return rx
}

// fn collect_poll<S: Stream>(mut s: S) -> Result<Vec<S::Item>, S::Error> {
//     let mut base = Vec::new();
//     loop {
//         match s.poll() {
//             Ok(item) => base.push(item),
//             Err(PollError::Empty) => return Ok(base),
//             Err(PollError::Other(e)) => return Err(e),
//             Err(PollError::NotReady) => panic!("blocked?"),
//         }
//     }
// }
//
#[test]
fn adapters() {
    assert_done(|| list().map(|a| a + 1).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| err_list().map_err(|a| a + 1).collect(), Err(4));
    assert_done(|| list().fold(0, |a, b| a + b), Ok(6));
    assert_done(|| err_list().fold(0, |a, b| a + b), Err(3));
    assert_done(|| list().filter(|a| *a % 2 == 0).collect(), Ok(vec![2]));
    assert_done(|| list().and_then(|a| Ok(a + 1)).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| list().then(|a| a.map(|e| e + 1)).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| list().and_then(|a| failed::<i32, u32>(a as u32)).collect(),
                Err(1));
    assert_done(|| err_list().or_else(|a| {
        finished::<i32, u32>(a as i32)
    }).collect(), Ok(vec![1, 2, 3]));
    assert_done(|| list().map(|_| list()).flat_map().collect(),
                Ok(vec![1, 2, 3, 1, 2, 3, 1, 2, 3]));
//     assert_eq!(list().map(|i| finished::<_, u32>(i)).flatten().collect(),
//                Ok(vec![1, 2, 3]));
}

// #[test]
// fn adapters_poll() {
//     assert_eq!(collect_poll(list().map(|a| a + 1)), Ok(vec![2, 3, 4]));
//     assert_eq!(collect_poll(err_list().map_err(|a| a + 1)), Err(4));
//     assert_eq!(collect_poll(list().filter(|a| *a % 2 == 0)), Ok(vec![2]));
//     assert_eq!(collect_poll(list().and_then(|a| Ok(a + 1))), Ok(vec![2, 3, 4]));
//     assert_eq!(collect_poll(err_list().and_then(|a| Ok(a + 1))), Err(3));
//     assert_eq!(collect_poll(err_list().and_then(|a| {
//         failed::<i32, _>(a as u32)
//     })), Err(1));
//     assert_eq!(collect_poll(err_list().or_else(|a| finished::<_, u32>(a as i32))),
//                Ok(vec![1, 2, 3]));
//
//     let (tx, rx) = channel::<i32, u32>();
//     let (rx2, tx2) = promise::pair();
//     let mut rx2 = Some(rx2);
//     let mut rx = rx.and_then(move |_a| rx2.take().unwrap());
//     match rx.poll() {
//         Err(PollError::NotReady) => {}
//         _ => panic!("ready?"),
//     }
//     tx.send(Ok(1)).schedule(|_| ());
//     match rx.poll() {
//         Err(PollError::NotReady) => {}
//         _ => panic!("ready?"),
//     }
//     match rx.poll() {
//         Err(PollError::NotReady) => {}
//         _ => panic!("ready?"),
//     }
//     tx2.finish(1);
//     match rx.poll() {
//         Ok(1) => {},
//         Err(PollError::NotReady) => panic!("not ready?"),
//         Err(PollError::Empty) => panic!("empty?"),
//         _ => panic!("not ready?"),
//     }
//
//     // let (tx, rx) = channel::<i32, u32>();
//     // let rx = rx.and_then(|a| failed::<i32, _>(a as u32));
//     // tx.send(Ok(1)).schedule(|_| ());
//     // assert_eq!(rx.collect(), Err(1));
//     // assert_eq!(list().fold(0, |a, b| a + b), Ok(6));
//     // assert_eq!(list().and_then(|a| Ok(a + 1)).collect(),
//     //            Ok(vec![2, 3, 4]));
//     // assert_eq!(err_list().or_else(|a| {
//     //     finished::<i32, u32>(a as i32)
//     // }).collect(), Ok(vec![1, 2, 3]));
//     // assert_eq!(list().map(|_| list()).flat_map().collect(),
//     //            Ok(vec![1, 2, 3, 1, 2, 3, 1, 2, 3]));
//     // assert_eq!(list().map(|i| finished::<_, u32>(i)).flatten().collect(),
//     //            Ok(vec![1, 2, 3]));
//
//     assert_eq!(list().collect().poll().ok().unwrap(), Ok(vec![1, 2, 3]));
//     assert_eq!(err_list().collect().poll().ok().unwrap(), Err(3));
//     assert_eq!(list().fold(0, |a, b| a + b).poll().ok().unwrap(), Ok(6));
//     assert_eq!(err_list().fold(0, |a, b| a + b).poll().ok().unwrap(), Err(3));
//     assert_eq!(list().map(|a| finished::<_, u32>(a))
//                      .flatten().collect().poll().ok().unwrap(),
//                Ok(vec![1, 2, 3]));
//     assert_eq!(list().map(|_a| list()).flat_map()
//                      .collect().poll().ok().unwrap(),
//                Ok(vec![1, 2, 3, 1, 2, 3, 1, 2, 3]));
// }
//
// #[test]
// fn rxdrop() {
//     let (tx, rx) = channel::<i32, u32>();
//     drop(rx);
//     assert!(tx.send(Ok(1)).is_err());
// }
//
// #[test]
// fn bufstream_smoke() {
//     let (tx, mut rx) = bufstream::<i32, u32>(4);
//     let (vrx, mut vtx): (Vec<_>, Vec<_>) = (0..4).map(|_| {
//         let (a, b) = promise::pair::<i32, u32>();
//         (a, Some(b))
//     }).unzip();
//     for (a, b) in tx.zip(vrx) {
//         b.schedule(|val| a.send(val));
//     }
//
//     assert_eq!(rx.poll(), Err(PollError::NotReady));
//     vtx[0].take().unwrap().finish(2);
//     assert_eq!(rx.poll(), Ok(2));
//     assert_eq!(rx.poll(), Err(PollError::NotReady));
//     vtx[3].take().unwrap().finish(4);
//     assert_eq!(rx.poll(), Ok(4));
//     assert_eq!(rx.poll(), Err(PollError::NotReady));
//     vtx[1].take().unwrap().fail(3);
//     assert_eq!(rx.poll(), Err(PollError::Other(3)));
//     assert_eq!(rx.poll(), Err(PollError::NotReady));
//     vtx[2].take().unwrap().finish(1);
//     assert_eq!(rx.poll(), Ok(1));
//     assert_eq!(rx.poll(), Err(PollError::Empty));
// }
//
// #[test]
// fn bufstream_concurrent() {
//     let (tx, rx) = bufstream::<i32, u32>(4);
//     let (vrx, vtx): (Vec<_>, Vec<_>) = (0..4).map(|_| {
//         promise::pair::<i32, u32>()
//     }).unzip();
//     for (a, b) in tx.zip(vrx) {
//         b.schedule(|val| a.send(val));
//     }
//
//     let t = thread::spawn(|| {
//         let mut it = vtx.into_iter();
//         it.next().unwrap().finish(2);
//         it.next_back().unwrap().finish(4);
//         it.next().unwrap().finish(3);
//         it.next_back().unwrap().finish(1);
//         assert!(it.next().is_none());
//     });
//
//     assert_eq!(rx.collect(), Ok(vec![2, 4, 3, 1]));
//     t.join().unwrap();
// }
<commit_msg>Fix the stream tests<commit_after>extern crate support;
extern crate futures;

use futures::{failed, finished, Future};
use futures::stream::*;
use support::*;

// #[test]
// fn smoke() {
//     let (tx, rx) = channel::<i32, u32>();
//     tx.send(Ok(1))
//       .and_then(|tx| tx.send(Ok(2)))
//       .and_then(|tx| tx.send(Ok(3)))
//       .schedule(|r| assert!(r.is_ok()));
//     assert_eq!(rx.collect(), Ok(vec![1, 2, 3]));
//
//     let (tx, rx) = channel::<i32, u32>();
//     tx.send(Ok(1))
//       .and_then(|tx| tx.send(Err(2)))
//       .and_then(|tx| tx.send(Ok(3)))
//       .schedule(|r| assert!(r.is_ok()));
//     assert_eq!(rx.collect(), Err(2));
// }

fn list() -> Receiver<i32, u32> {
    let (tx, rx) = channel();
    tx.send(Ok(1))
      .and_then(|tx| tx.send(Ok(2)))
      .and_then(|tx| tx.send(Ok(3)))
      .forget();
    return rx
}

fn err_list() -> Receiver<i32, u32> {
    let (tx, rx) = channel();
    tx.send(Ok(1))
      .and_then(|tx| tx.send(Ok(2)))
      .and_then(|tx| tx.send(Err(3)))
      .forget();
    return rx
}

// fn collect_poll<S: Stream>(mut s: S) -> Result<Vec<S::Item>, S::Error> {
//     let mut base = Vec::new();
//     loop {
//         match s.poll() {
//             Ok(item) => base.push(item),
//             Err(PollError::Empty) => return Ok(base),
//             Err(PollError::Other(e)) => return Err(e),
//             Err(PollError::NotReady) => panic!("blocked?"),
//         }
//     }
// }
//
#[test]
fn adapters() {
    assert_done(|| list().map(|a| a + 1).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| err_list().map_err(|a| a + 1).collect(), Err(4));
    assert_done(|| list().fold(0, |a, b| a + b), Ok(6));
    assert_done(|| err_list().fold(0, |a, b| a + b), Err(3));
    assert_done(|| list().filter(|a| *a % 2 == 0).collect(), Ok(vec![2]));
    assert_done(|| list().and_then(|a| Ok(a + 1)).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| list().then(|a| a.map(|e| e + 1)).collect(), Ok(vec![2, 3, 4]));
    assert_done(|| list().and_then(|a| failed::<i32, u32>(a as u32)).collect(),
                Err(1));
    assert_done(|| err_list().or_else(|a| {
        finished::<i32, u32>(a as i32)
    }).collect(), Ok(vec![1, 2, 3]));
    assert_done(|| list().map(|_| list()).flatten().collect(),
                Ok(vec![1, 2, 3, 1, 2, 3, 1, 2, 3]));
//     assert_eq!(list().map(|i| finished::<_, u32>(i)).flatten().collect(),
//                Ok(vec![1, 2, 3]));
}

// #[test]
// fn adapters_poll() {
//     assert_eq!(collect_poll(list().map(|a| a + 1)), Ok(vec![2, 3, 4]));
//     assert_eq!(collect_poll(err_list().map_err(|a| a + 1)), Err(4));
//     assert_eq!(collect_poll(list().filter(|a| *a % 2 == 0)), Ok(vec![2]));
//     assert_eq!(collect_poll(list().and_then(|a| Ok(a + 1))), Ok(vec![2, 3, 4]));
//     assert_eq!(collect_poll(err_list().and_then(|a| Ok(a + 1))), Err(3));
//     assert_eq!(collect_poll(err_list().and_then(|a| {
//         failed::<i32, _>(a as u32)
//     })), Err(1));
//     assert_eq!(collect_poll(err_list().or_else(|a| finished::<_, u32>(a as i32))),
//                Ok(vec![1, 2, 3]));
//
//     let (tx, rx) = channel::<i32, u32>();
//     let (rx2, tx2) = promise::pair();
//     let mut rx2 = Some(rx2);
//     let mut rx = rx.and_then(move |_a| rx2.take().unwrap());
//     match rx.poll() {
//         Err(PollError::NotReady) => {}
//         _ => panic!("ready?"),
//     }
//     tx.send(Ok(1)).schedule(|_| ());
//     match rx.poll() {
//         Err(PollError::NotReady) => {}
//         _ => panic!("ready?"),
//     }
//     match rx.poll() {
//         Err(PollError::NotReady) => {}
//         _ => panic!("ready?"),
//     }
//     tx2.finish(1);
//     match rx.poll() {
//         Ok(1) => {},
//         Err(PollError::NotReady) => panic!("not ready?"),
//         Err(PollError::Empty) => panic!("empty?"),
//         _ => panic!("not ready?"),
//     }
//
//     // let (tx, rx) = channel::<i32, u32>();
//     // let rx = rx.and_then(|a| failed::<i32, _>(a as u32));
//     // tx.send(Ok(1)).schedule(|_| ());
//     // assert_eq!(rx.collect(), Err(1));
//     // assert_eq!(list().fold(0, |a, b| a + b), Ok(6));
//     // assert_eq!(list().and_then(|a| Ok(a + 1)).collect(),
//     //            Ok(vec![2, 3, 4]));
//     // assert_eq!(err_list().or_else(|a| {
//     //     finished::<i32, u32>(a as i32)
//     // }).collect(), Ok(vec![1, 2, 3]));
//     // assert_eq!(list().map(|_| list()).flat_map().collect(),
//     //            Ok(vec![1, 2, 3, 1, 2, 3, 1, 2, 3]));
//     // assert_eq!(list().map(|i| finished::<_, u32>(i)).flatten().collect(),
//     //            Ok(vec![1, 2, 3]));
//
//     assert_eq!(list().collect().poll().ok().unwrap(), Ok(vec![1, 2, 3]));
//     assert_eq!(err_list().collect().poll().ok().unwrap(), Err(3));
//     assert_eq!(list().fold(0, |a, b| a + b).poll().ok().unwrap(), Ok(6));
//     assert_eq!(err_list().fold(0, |a, b| a + b).poll().ok().unwrap(), Err(3));
//     assert_eq!(list().map(|a| finished::<_, u32>(a))
//                      .flatten().collect().poll().ok().unwrap(),
//                Ok(vec![1, 2, 3]));
//     assert_eq!(list().map(|_a| list()).flat_map()
//                      .collect().poll().ok().unwrap(),
//                Ok(vec![1, 2, 3, 1, 2, 3, 1, 2, 3]));
// }
//
// #[test]
// fn rxdrop() {
//     let (tx, rx) = channel::<i32, u32>();
//     drop(rx);
//     assert!(tx.send(Ok(1)).is_err());
// }
//
// #[test]
// fn bufstream_smoke() {
//     let (tx, mut rx) = bufstream::<i32, u32>(4);
//     let (vrx, mut vtx): (Vec<_>, Vec<_>) = (0..4).map(|_| {
//         let (a, b) = promise::pair::<i32, u32>();
//         (a, Some(b))
//     }).unzip();
//     for (a, b) in tx.zip(vrx) {
//         b.schedule(|val| a.send(val));
//     }
//
//     assert_eq!(rx.poll(), Err(PollError::NotReady));
//     vtx[0].take().unwrap().finish(2);
//     assert_eq!(rx.poll(), Ok(2));
//     assert_eq!(rx.poll(), Err(PollError::NotReady));
//     vtx[3].take().unwrap().finish(4);
//     assert_eq!(rx.poll(), Ok(4));
//     assert_eq!(rx.poll(), Err(PollError::NotReady));
//     vtx[1].take().unwrap().fail(3);
//     assert_eq!(rx.poll(), Err(PollError::Other(3)));
//     assert_eq!(rx.poll(), Err(PollError::NotReady));
//     vtx[2].take().unwrap().finish(1);
//     assert_eq!(rx.poll(), Ok(1));
//     assert_eq!(rx.poll(), Err(PollError::Empty));
// }
//
// #[test]
// fn bufstream_concurrent() {
//     let (tx, rx) = bufstream::<i32, u32>(4);
//     let (vrx, vtx): (Vec<_>, Vec<_>) = (0..4).map(|_| {
//         promise::pair::<i32, u32>()
//     }).unzip();
//     for (a, b) in tx.zip(vrx) {
//         b.schedule(|val| a.send(val));
//     }
//
//     let t = thread::spawn(|| {
//         let mut it = vtx.into_iter();
//         it.next().unwrap().finish(2);
//         it.next_back().unwrap().finish(4);
//         it.next().unwrap().finish(3);
//         it.next_back().unwrap().finish(1);
//         assert!(it.next().is_none());
//     });
//
//     assert_eq!(rx.collect(), Ok(vec![2, 4, 3, 1]));
//     t.join().unwrap();
// }
<|endoftext|>


<commit_before>extern crate rusqlite;
use super::sql_queries::sqlite3 as queries;
pub use super::base::SKStore;
use rusqlite::SqliteConnection;
// mod sql_queries;
// mod base;

pub struct SKSqliteStore<'a, 'b> {
    path: &'a str,
    conn: Option<&'b SqliteConnection>
}

impl<'a, 'b> SKSqliteStore<'a, 'b> {
    pub fn new(file: &'a str) -> SKSqliteStore {
        let store = SKSqliteStore { path: file, conn: None };
        store
    }
}

impl<'a, 'b> SKStore for SKSqliteStore<'a, 'b> {
    fn init(&self) {
        println!("Initializing database.");
    }
    fn connect(&mut self) {
        let conn = match self.conn {
            Some(c) => c,
            None => {
                SqliteConnection::open(self.path).unwrap()
            }
        };
        Some(conn);
        /*
        match self {
            &mut SKSqliteStore { conn: Some(_), .. } => true,
            &mut SKSqliteStore { conn: None, path: p } => {
                /*
                let c = SqliteConnection::open(p).unwrap();
                self.conn = Some(&mut c);
                */
                self.conn = Some(&mut SqliteConnection::open(p).unwrap());
                false
            }
        };
        */
        println!("Connected to {}.", self.path);
    }
    fn disconnect(&mut self) {
        match self.conn {
            Some(c) => { c.close(); self.conn = None; true }
            None => false
        };
        println!("Disconnected from {}.", self.path);
    }
}

mod tests {
    use super::*;

    #[test]
    fn test_setup_new_db() {
        let store = SKSqliteStore::new("test.db");
        assert_eq!(store.path, "test.db");
    }
}
<commit_msg>It's don't werking.<commit_after>extern crate rusqlite;
use super::sql_queries::sqlite3 as queries;
pub use super::base::SKStore;
use rusqlite::SqliteConnection;
// mod sql_queries;
// mod base;

pub struct SKSqliteStore<'a, 'b> {
    path: &'a str,
    conn: Option<SqliteConnection>
}

impl<'a, 'b> SKSqliteStore<'a, 'b> {
    pub fn new(file: &'a str) -> SKSqliteStore {
        let store = SKSqliteStore { path: file, conn: &None };
        store
    }
}

impl<'a, 'b> SKStore for SKSqliteStore<'a, 'b> {
    fn init(&self) {
        println!("Initializing database.");
    }
    fn connect(&mut self) {
        /*
        let conn = match self.conn {
            &Some(ref c) => c,
            &None => {
                &SqliteConnection::open(self.path).unwrap()
            }
        };
        &Some(*conn);
        */
        /*
        match self {
            &mut SKSqliteStore { conn: Some(_), .. } => true,
            &mut SKSqliteStore { conn: None, path: p } => {
                /*
                let c = SqliteConnection::open(p).unwrap();
                self.conn = Some(&mut c);
                */
                self.conn = Some(&mut SqliteConnection::open(p).unwrap());
                false
            }
        };
        */
        if *self.conn == &None {
            self.conn = &Some(SqliteConnection::open(self.path).unwrap());
        }
        println!("Connected to {}.", self.path);
    }
    fn disconnect(&mut self) {
        match self.conn {
            &Some(c) => { c.close(); self.conn = &None; true }
            &None => false
        };
        println!("Disconnected from {}.", self.path);
    }
}

mod tests {
    use super::*;

    #[test]
    fn test_setup_new_db() {
        let store = SKSqliteStore::new("test.db");
        assert_eq!(store.path, "test.db");
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate sputnikvm;
extern crate bigint;
extern crate serde_json;
extern crate gethrpc;

use serde_json::{Value};
use std::process;
use std::fs::File;
use std::path::Path;
use std::io::{BufReader};
use std::str::FromStr;
use std::collections::HashMap;

use sputnikvm::{Gas, Address};
use bigint::{U256, M256, read_hex};
use sputnikvm::vm::{BlockHeader, Context, SeqTransactionVM, Transaction, VM, Log, Patch, AccountCommitment, Account, FRONTIER_PATCH};
use sputnikvm::vm::errors::RequireError;
use gethrpc::{regression, GethRPCClient, RPCCall, RPCBlock, RPCTransaction, RPCLog};

fn from_rpc_block(block: &RPCBlock) -> BlockHeader {
    BlockHeader {
        coinbase: Address::from_str(&block.miner).unwrap(),
        timestamp: M256::from_str(&block.timestamp).unwrap(),
        number: M256::from_str(&block.number).unwrap(),
        difficulty: M256::from_str(&block.difficulty).unwrap(),
        gas_limit: Gas::from_str(&block.gasLimit).unwrap(),
    }
}

fn from_rpc_transaction(transaction: &RPCTransaction) -> Transaction {
    if transaction.to.is_empty() {
        Transaction::ContractCreation {
            caller: Address::from_str(&transaction.from).unwrap(),
            value: U256::from_str(&transaction.value).unwrap(),
            gas_limit: Gas::from_str(&transaction.gas).unwrap(),
            gas_price: Gas::from_str(&transaction.gasPrice).unwrap(),
            init: read_hex(&transaction.input).unwrap(),
        }
    } else {
        Transaction::MessageCall {
            caller: Address::from_str(&transaction.from).unwrap(),
            address: Address::from_str(&transaction.to).unwrap(),
            value: U256::from_str(&transaction.value).unwrap(),
            gas_limit: Gas::from_str(&transaction.gas).unwrap(),
            gas_price: Gas::from_str(&transaction.gasPrice).unwrap(),
            data: read_hex(&transaction.input).unwrap(),
        }
    }
}

fn from_rpc_log(log: &RPCLog) -> Log {
    let mut topics: Vec<M256> = Vec::new();
    for topic in &log.topics {
        topics.push(M256::from_str(&topic).unwrap());
    }
    Log {
        address: Address::from_str(&log.address).unwrap(),
        data: read_hex(&log.data).unwrap(),
        topics: topics,
    }
}

fn handle_fire(client: &mut GethRPCClient, vm: &mut SeqTransactionVM, last_block_number: &str) {
    loop {
        match vm.fire() {
            Ok(()) => {
                println!("VM exited with {:?}.", vm.status());
                break;
            },
            Err(RequireError::Account(address)) => {
                println!("Feeding VM account at 0x{:x} ...", address);
                let nonce = M256::from_str(&client.get_transaction_count(&format!("0x{:x}", address),
                                                                         &last_block_number)).unwrap();
                let balance = U256::from_str(&client.get_balance(&format!("0x{:x}", address),
                                                                 &last_block_number)).unwrap();
                let code = read_hex(&client.get_code(&format!("0x{:x}", address),
                                                     &last_block_number)).unwrap();
                vm.commit_account(AccountCommitment::Full {
                    nonce: nonce,
                    address: address,
                    balance: balance,
                    code: code,
                });
            },
            Err(RequireError::AccountStorage(address, index)) => {
                println!("Feeding VM account storage at 0x{:x} with index 0x{:x} ...", address, index);
                let value = M256::from_str(&client.get_storage_at(&format!("0x{:x}", address),
                                                                  &format!("0x{:x}", index),
                                                                  &last_block_number)).unwrap();
                vm.commit_account(AccountCommitment::Storage {
                    address: address,
                    index: index,
                    value: value,
                });
            },
            Err(RequireError::AccountCode(address)) => {
                println!("Feeding VM account code at 0x{:x} ...", address);
                let code = read_hex(&client.get_code(&format!("0x{:x}", address),
                                                     &last_block_number)).unwrap();
                vm.commit_account(AccountCommitment::Code {
                    address: address,
                    code: code,
                });
            }
            Err(err) => {
                println!("Unhandled require: {:?}", err);
                unimplemented!()
            },
        }
    }
}

fn test_block(client: &mut GethRPCClient, number: usize) {
    let block = client.get_block_by_number(format!("0x{:x}", number).as_str());
    println!("block {}, transaction count: {}", block.number, block.transactions.len());
    let last_number = format!("0x{:x}", number - 1);
    let cur_number = block.number.to_string();
    let block_header = from_rpc_block(&block);

    let mut last_vm: Option<SeqTransactionVM> = None;
    for transaction_hash in block.transactions {
        println!("\nworking on transaction {}", transaction_hash);
        let transaction = from_rpc_transaction(&client.get_transaction_by_hash(&transaction_hash));
        let receipt = client.get_transaction_receipt(&transaction_hash);

        let mut vm = if last_vm.is_none() {
            SeqTransactionVM::new(transaction, block_header.clone(), &FRONTIER_PATCH)
        } else {
            SeqTransactionVM::with_previous(transaction, block_header.clone(), &FRONTIER_PATCH, last_vm.as_ref().unwrap())
        };

        handle_fire(client, &mut vm, &last_number);

        assert!(Gas::from_str(&receipt.gasUsed).unwrap() == vm.real_used_gas());
        assert!(receipt.logs.len() == vm.logs().len());
        for i in 0..receipt.logs.len() {
            assert!(from_rpc_log(&receipt.logs[i]) == vm.logs()[i]);
        }

        last_vm = Some(vm);
    }

    if last_vm.is_some() {
        for account in last_vm.as_ref().unwrap().accounts() {
            match account {
                &Account::Full {
                    address,
                    balance,
                    ref changing_storage,
                    ..
                } => {
                    let expected_balance = client.get_balance(&format!("0x{:x}", address),
                                                              &cur_number);
                    assert!(U256::from_str(&expected_balance).unwrap() == balance);
                    let changing_storage: HashMap<M256, M256> = changing_storage.clone().into();
                    for (key, value) in changing_storage {
                        let expected_value = client.get_storage_at(&format!("0x{:x}", address),
                                                                   &format!("0x{:x}", key),
                                                                   &cur_number);
                        assert!(M256::from_str(&expected_value).unwrap() == value);
                    }
                },
                &Account::Create {
                    address,
                    balance,
                    ref storage,
                    ..
                } => {
                    let expected_balance = client.get_balance(&format!("0x{:x}", address),
                                                              &cur_number);
                    assert!(U256::from_str(&expected_balance).unwrap() == balance);
                    let storage: HashMap<M256, M256> = storage.clone().into();
                    for (key, value) in storage {
                        let expected_value = client.get_storage_at(&format!("0x{:x}", address),
                                                                   &format!("0x{:x}", key),
                                                                   &cur_number);
                        assert!(M256::from_str(&expected_value).unwrap() == value);
                    }
                },
                &Account::Remove(address) => {
                    let expected_balance = client.get_balance(&format!("0x{:x}", address),
                                                              &cur_number);
                    assert!(U256::from_str(&expected_balance).unwrap() == U256::zero());
                },
                &Account::IncreaseBalance(address, balance) => {
                    let last_balance = client.get_balance(&format!("0x{:x}", address),
                                                          &last_number);
                    let cur_balance = client.get_balance(&format!("0x{:x}", address),
                                                         &cur_number);

                    assert!(U256::from_str(&last_balance).unwrap() + balance ==
                            U256::from_str(&cur_balance).unwrap());
                },
                &Account::DecreaseBalance(address, balance) => {
                    let last_balance = client.get_balance(&format!("0x{:x}", address),
                                                          &last_number);
                    let cur_balance = client.get_balance(&format!("0x{:x}", address),
                                                         &cur_number);

                    assert!(U256::from_str(&last_balance).unwrap() - balance ==
                            U256::from_str(&cur_balance).unwrap());
                },
            }
        }
    }
}

fn main() {
    let matches = clap_app!(regtests =>
        (version: "0.1")
        (author: "Ethereum Classic Contributors")
        (about: "Performs an regression test on the entire Ethereum Classic blockchain.\n\nSteps to reproduce:\n* Install Ethereum Classic Geth: `$ go install github.com/ethereumproject/go-ethereum/cmd/geth`.\n* Run Geth with this command: `$ ~/go/bin/geth --rpc --rpcaddr 127.0.0.1 --rpcport 8545`.\n* Wait for the chain to sync.\n* Change directory into the `regtests` directory `$ cd regtests`\n* Run this command: `$ RUST_BACKTRACE=1 cargo run --bin regtests -- -r http://127.0.0.1:8545")
        (@arg RPC: -r --rpc +takes_value +required "Domain of Ethereum Classic Geth's RPC endpoint. e.g. `-r http://127.0.0.1:8545`.")
        (@arg NUMBER: -n --number +takes_value + required "Block number to run this test. Radix is 10. e.g. `-n 49439`.")
    ).get_matches();

    let address = matches.value_of("RPC").unwrap();
    let number = matches.value_of("NUMBER").unwrap();
    let mut client = GethRPCClient::new(address);
    println!("net version: {}", client.net_version());

    if number.contains("..") {
        let number: Vec<&str> = number.split("..").collect();
        let from = usize::from_str_radix(&number[0], 10).unwrap();
        let to = usize::from_str_radix(&number[1], 10).unwrap();
        for n in from..to {
            test_block(&mut client, n);
        }
    } else {
        let number = usize::from_str_radix(&number, 10).unwrap();
        test_block(&mut client, number);
    }
}
<commit_msg>Problem: block 46859 regression failure<commit_after>#[macro_use]
extern crate clap;
extern crate sputnikvm;
extern crate bigint;
extern crate serde_json;
extern crate gethrpc;

use serde_json::{Value};
use std::process;
use std::fs::File;
use std::path::Path;
use std::io::{BufReader};
use std::str::FromStr;
use std::collections::HashMap;

use sputnikvm::{Gas, Address};
use bigint::{U256, M256, read_hex};
use sputnikvm::vm::{BlockHeader, Context, SeqTransactionVM, Transaction, VM, Log, Patch, AccountCommitment, Account, FRONTIER_PATCH};
use sputnikvm::vm::errors::RequireError;
use gethrpc::{regression, GethRPCClient, RPCCall, RPCBlock, RPCTransaction, RPCLog};

fn from_rpc_block(block: &RPCBlock) -> BlockHeader {
    BlockHeader {
        coinbase: Address::from_str(&block.miner).unwrap(),
        timestamp: M256::from_str(&block.timestamp).unwrap(),
        number: M256::from_str(&block.number).unwrap(),
        difficulty: M256::from_str(&block.difficulty).unwrap(),
        gas_limit: Gas::from_str(&block.gasLimit).unwrap(),
    }
}

fn from_rpc_transaction(transaction: &RPCTransaction) -> Transaction {
    if transaction.to.is_empty() {
        Transaction::ContractCreation {
            caller: Address::from_str(&transaction.from).unwrap(),
            value: U256::from_str(&transaction.value).unwrap(),
            gas_limit: Gas::from_str(&transaction.gas).unwrap(),
            gas_price: Gas::from_str(&transaction.gasPrice).unwrap(),
            init: read_hex(&transaction.input).unwrap(),
        }
    } else {
        Transaction::MessageCall {
            caller: Address::from_str(&transaction.from).unwrap(),
            address: Address::from_str(&transaction.to).unwrap(),
            value: U256::from_str(&transaction.value).unwrap(),
            gas_limit: Gas::from_str(&transaction.gas).unwrap(),
            gas_price: Gas::from_str(&transaction.gasPrice).unwrap(),
            data: read_hex(&transaction.input).unwrap(),
        }
    }
}

fn from_rpc_log(log: &RPCLog) -> Log {
    let mut topics: Vec<M256> = Vec::new();
    for topic in &log.topics {
        topics.push(M256::from_str(&topic).unwrap());
    }
    Log {
        address: Address::from_str(&log.address).unwrap(),
        data: read_hex(&log.data).unwrap(),
        topics: topics,
    }
}

fn handle_fire(client: &mut GethRPCClient, vm: &mut SeqTransactionVM, last_block_number: &str) {
    loop {
        match vm.fire() {
            Ok(()) => {
                println!("VM exited with {:?}.", vm.status());
                break;
            },
            Err(RequireError::Account(address)) => {
                println!("Feeding VM account at 0x{:x} ...", address);
                let nonce = M256::from_str(&client.get_transaction_count(&format!("0x{:x}", address),
                                                                         &last_block_number)).unwrap();
                let balance = U256::from_str(&client.get_balance(&format!("0x{:x}", address),
                                                                 &last_block_number)).unwrap();
                let code = read_hex(&client.get_code(&format!("0x{:x}", address),
                                                     &last_block_number)).unwrap();
                vm.commit_account(AccountCommitment::Full {
                    nonce: nonce,
                    address: address,
                    balance: balance,
                    code: code,
                });
            },
            Err(RequireError::AccountStorage(address, index)) => {
                println!("Feeding VM account storage at 0x{:x} with index 0x{:x} ...", address, index);
                let value = M256::from_str(&client.get_storage_at(&format!("0x{:x}", address),
                                                                  &format!("0x{:x}", index),
                                                                  &last_block_number)).unwrap();
                vm.commit_account(AccountCommitment::Storage {
                    address: address,
                    index: index,
                    value: value,
                });
            },
            Err(RequireError::AccountCode(address)) => {
                println!("Feeding VM account code at 0x{:x} ...", address);
                let code = read_hex(&client.get_code(&format!("0x{:x}", address),
                                                     &last_block_number)).unwrap();
                vm.commit_account(AccountCommitment::Code {
                    address: address,
                    code: code,
                });
            }
            Err(err) => {
                println!("Unhandled require: {:?}", err);
                unimplemented!()
            },
        }
    }
}

fn is_miner_or_uncle(address: Address, block: &RPCBlock, client: &mut GethRPCClient) -> bool {
    // Give up balance testing if the address is a miner or an uncle.

    let miner = Address::from_str(&block.miner).unwrap();
    if miner == address {
        return true;
    }
    if block.uncles.len() > 0 {
        for uncle_hash in &block.uncles {
            let uncle = client.get_block_by_hash(&uncle_hash);
            let uncle_miner = Address::from_str(&uncle.miner).unwrap();
            if uncle_miner == address {
                return true;
            }
        }
    }

    return false;
}

fn test_block(client: &mut GethRPCClient, number: usize) {
    let block = client.get_block_by_number(format!("0x{:x}", number).as_str());
    println!("block {}, transaction count: {}", block.number, block.transactions.len());
    let last_number = format!("0x{:x}", number - 1);
    let cur_number = block.number.to_string();
    let block_header = from_rpc_block(&block);

    let mut last_vm: Option<SeqTransactionVM> = None;
    for transaction_hash in &block.transactions {
        println!("\nworking on transaction {}", transaction_hash);
        let transaction = from_rpc_transaction(&client.get_transaction_by_hash(&transaction_hash));
        let receipt = client.get_transaction_receipt(&transaction_hash);

        let mut vm = if last_vm.is_none() {
            SeqTransactionVM::new(transaction, block_header.clone(), &FRONTIER_PATCH)
        } else {
            SeqTransactionVM::with_previous(transaction, block_header.clone(), &FRONTIER_PATCH, last_vm.as_ref().unwrap())
        };

        handle_fire(client, &mut vm, &last_number);

        assert!(Gas::from_str(&receipt.gasUsed).unwrap() == vm.real_used_gas());
        assert!(receipt.logs.len() == vm.logs().len());
        for i in 0..receipt.logs.len() {
            assert!(from_rpc_log(&receipt.logs[i]) == vm.logs()[i]);
        }

        last_vm = Some(vm);
    }

    if last_vm.is_some() {
        for account in last_vm.as_ref().unwrap().accounts() {
            match account {
                &Account::Full {
                    address,
                    balance,
                    ref changing_storage,
                    ..
                } => {
                    if !is_miner_or_uncle(address, &block, client) {
                        let expected_balance = client.get_balance(&format!("0x{:x}", address),
                                                                  &cur_number);
                        assert!(U256::from_str(&expected_balance).unwrap() == balance);
                    }
                    let changing_storage: HashMap<M256, M256> = changing_storage.clone().into();
                    for (key, value) in changing_storage {
                        let expected_value = client.get_storage_at(&format!("0x{:x}", address),
                                                                   &format!("0x{:x}", key),
                                                                   &cur_number);
                        assert!(M256::from_str(&expected_value).unwrap() == value);
                    }
                },
                &Account::Create {
                    address,
                    balance,
                    ref storage,
                    ..
                } => {
                    if !is_miner_or_uncle(address, &block, client) {
                        let expected_balance = client.get_balance(&format!("0x{:x}", address),
                                                                  &cur_number);
                        assert!(U256::from_str(&expected_balance).unwrap() == balance);
                    }
                    let storage: HashMap<M256, M256> = storage.clone().into();
                    for (key, value) in storage {
                        let expected_value = client.get_storage_at(&format!("0x{:x}", address),
                                                                   &format!("0x{:x}", key),
                                                                   &cur_number);
                        assert!(M256::from_str(&expected_value).unwrap() == value);
                    }
                },
                &Account::Remove(address) => {
                    if !is_miner_or_uncle(address, &block, client) {
                        let expected_balance = client.get_balance(&format!("0x{:x}", address),
                                                                  &cur_number);
                        assert!(U256::from_str(&expected_balance).unwrap() == U256::zero());
                    }
                },
                &Account::IncreaseBalance(address, balance) => {
                    if !is_miner_or_uncle(address, &block, client) {
                        let last_balance = client.get_balance(&format!("0x{:x}", address),
                                                              &last_number);
                        let cur_balance = client.get_balance(&format!("0x{:x}", address),
                                                             &cur_number);

                        assert!(U256::from_str(&last_balance).unwrap() + balance ==
                                U256::from_str(&cur_balance).unwrap());
                    }
                },
                &Account::DecreaseBalance(address, balance) => {
                    if !is_miner_or_uncle(address, &block, client) {
                        let last_balance = client.get_balance(&format!("0x{:x}", address),
                                                              &last_number);
                        let cur_balance = client.get_balance(&format!("0x{:x}", address),
                                                             &cur_number);

                        assert!(U256::from_str(&last_balance).unwrap() - balance ==
                                U256::from_str(&cur_balance).unwrap());
                    }
                },
            }
        }
    }
}

fn main() {
    let matches = clap_app!(regtests =>
        (version: "0.1")
        (author: "Ethereum Classic Contributors")
        (about: "Performs an regression test on the entire Ethereum Classic blockchain.\n\nSteps to reproduce:\n* Install Ethereum Classic Geth: `$ go install github.com/ethereumproject/go-ethereum/cmd/geth`.\n* Run Geth with this command: `$ ~/go/bin/geth --rpc --rpcaddr 127.0.0.1 --rpcport 8545`.\n* Wait for the chain to sync.\n* Change directory into the `regtests` directory `$ cd regtests`\n* Run this command: `$ RUST_BACKTRACE=1 cargo run --bin regtests -- -r http://127.0.0.1:8545")
        (@arg RPC: -r --rpc +takes_value +required "Domain of Ethereum Classic Geth's RPC endpoint. e.g. `-r http://127.0.0.1:8545`.")
        (@arg NUMBER: -n --number +takes_value + required "Block number to run this test. Radix is 10. e.g. `-n 49439`.")
    ).get_matches();

    let address = matches.value_of("RPC").unwrap();
    let number = matches.value_of("NUMBER").unwrap();
    let mut client = GethRPCClient::new(address);
    println!("net version: {}", client.net_version());

    if number.contains("..") {
        let number: Vec<&str> = number.split("..").collect();
        let from = usize::from_str_radix(&number[0], 10).unwrap();
        let to = usize::from_str_radix(&number[1], 10).unwrap();
        for n in from..to {
            test_block(&mut client, n);
        }
    } else {
        let number = usize::from_str_radix(&number, 10).unwrap();
        test_block(&mut client, number);
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::collections::hash_map::HashMap;
use std::fmt;
use std::io::Write;
use std::sync::mpsc::{channel, Sender, Receiver};

use crossbeam::{self, Scope};
use term::color::YELLOW;

use core::{PackageId, Target, Profile};
use util::{Config, DependencyQueue, Fresh, Dirty, Freshness};
use util::{CargoResult, ProcessBuilder, profile, internal, human};
use {handle_error};

use super::{Context, Kind, Unit};
use super::job::Job;

/// A management structure of the entire dependency graph to compile.
///
/// This structure is backed by the `DependencyQueue` type and manages the
/// actual compilation step of each package. Packages enqueue units of work and
/// then later on the entire graph is processed and compiled.
pub struct JobQueue<'a> {
    jobs: usize,
    queue: DependencyQueue<Key<'a>, Vec<(Job, Freshness)>>,
    tx: Sender<(Key<'a>, Message)>,
    rx: Receiver<(Key<'a>, Message)>,
    active: usize,
    pending: HashMap<Key<'a>, PendingBuild>,
    compiled: HashSet<&'a PackageId>,
    documented: HashSet<&'a PackageId>,
    counts: HashMap<&'a PackageId, usize>,
    is_release: bool,
}

/// A helper structure for metadata about the state of a building package.
struct PendingBuild {
    /// Number of jobs currently active
    amt: usize,
    /// Current freshness state of this package. Any dirty target within a
    /// package will cause the entire package to become dirty.
    fresh: Freshness,
}

#[derive(Clone, Copy, Eq, PartialEq, Hash)]
struct Key<'a> {
    pkg: &'a PackageId,
    target: &'a Target,
    profile: &'a Profile,
    kind: Kind,
}

pub struct JobState<'a> {
    tx: Sender<(Key<'a>, Message)>,
    key: Key<'a>,
}

enum Message {
    Run(String),
    Stdout(String),
    Stderr(String),
    Finish(CargoResult<()>),
}

impl<'a> JobState<'a> {
    pub fn running(&self, cmd: &ProcessBuilder) {
        let _ = self.tx.send((self.key, Message::Run(cmd.to_string())));
    }

    pub fn stdout(&self, out: &str) {
        let _ = self.tx.send((self.key, Message::Stdout(out.to_string())));
    }

    pub fn stderr(&self, err: &str) {
        let _ = self.tx.send((self.key, Message::Stderr(err.to_string())));
    }
}

impl<'a> JobQueue<'a> {
    pub fn new<'cfg>(cx: &Context<'a, 'cfg>) -> JobQueue<'a> {
        let (tx, rx) = channel();
        JobQueue {
            jobs: cx.jobs() as usize,
            queue: DependencyQueue::new(),
            tx: tx,
            rx: rx,
            active: 0,
            pending: HashMap::new(),
            compiled: HashSet::new(),
            documented: HashSet::new(),
            counts: HashMap::new(),
            is_release: cx.build_config.release,
        }
    }

    pub fn enqueue<'cfg>(&mut self,
                         cx: &Context<'a, 'cfg>,
                         unit: &Unit<'a>,
                         job: Job,
                         fresh: Freshness) -> CargoResult<()> {
        let key = Key::new(unit);
        let deps = key.dependencies(cx)?;
        self.queue.queue(Fresh, key, Vec::new(), &deps).push((job, fresh));
        *self.counts.entry(key.pkg).or_insert(0) += 1;
        Ok(())
    }

    /// Execute all jobs necessary to build the dependency graph.
    ///
    /// This function will spawn off `config.jobs()` workers to build all of the
    /// necessary dependencies, in order. Freshness is propagated as far as
    /// possible along each dependency chain.
    pub fn execute(&mut self, cx: &mut Context) -> CargoResult<()> {
        let _p = profile::start("executing the job graph");

        crossbeam::scope(|scope| {
            self.drain_the_queue(cx, scope)
        })
    }

    fn drain_the_queue(&mut self, cx: &mut Context, scope: &Scope<'a>)
                       -> CargoResult<()> {
        use std::time::Instant;

        let mut queue = Vec::new();
        trace!("queue: {:#?}", self.queue);

        // Iteratively execute the entire dependency graph. Each turn of the
        // loop starts out by scheduling as much work as possible (up to the
        // maximum number of parallel jobs). A local queue is maintained
        // separately from the main dependency queue as one dequeue may actually
        // dequeue quite a bit of work (e.g. 10 binaries in one project).
        //
        // After a job has finished we update our internal state if it was
        // successful and otherwise wait for pending work to finish if it failed
        // and then immediately return.
        let mut error = None;
        let start_time = Instant::now();
        loop {
            while error.is_none() && self.active < self.jobs {
                if !queue.is_empty() {
                    let (key, job, fresh) = queue.remove(0);
                    self.run(key, fresh, job, cx.config, scope)?;
                } else if let Some((fresh, key, jobs)) = self.queue.dequeue() {
                    let total_fresh = jobs.iter().fold(fresh, |fresh, &(_, f)| {
                        f.combine(fresh)
                    });
                    self.pending.insert(key, PendingBuild {
                        amt: jobs.len(),
                        fresh: total_fresh,
                    });
                    queue.extend(jobs.into_iter().map(|(job, f)| {
                        (key, job, f.combine(fresh))
                    }));
                } else {
                    break
                }
            }
            if self.active == 0 {
                break
            }

            let (key, msg) = self.rx.recv().unwrap();

            match msg {
                Message::Run(cmd) => {
                    cx.config.shell().verbose(|c| c.status("Running", &cmd))?;
                }
                Message::Stdout(out) => {
                    if cx.config.extra_verbose() {
                        writeln!(cx.config.shell().out(), "{}", out)?;
                    }
                }
                Message::Stderr(err) => {
                    if cx.config.extra_verbose() {
                        writeln!(cx.config.shell().err(), "{}", err)?;
                    }
                }
                Message::Finish(result) => {
                    info!("end: {:?}", key);
                    self.active -= 1;
                    match result {
                        Ok(()) => self.finish(key, cx)?,
                        Err(e) => {
                            handle_error(&*e, &mut *cx.config.shell());

                            if self.active > 0 {
                                cx.config.shell().say(
                                            "Build failed, waiting for other \
                                             jobs to finish...", YELLOW)?;
                            }
                            if error.is_none() {
                                error = Some(human("build failed"));
                            }
                        }
                    }
                }
            }
        }

        let build_type = if self.is_release { "release" } else { "dev" };
        let profile = cx.lib_profile();
        let mut opt_type = String::from(if profile.opt_level == "0" { "unoptimized" }
                                        else { "optimized" });
        if profile.debuginfo.is_some() {
            opt_type = opt_type + " + debuginfo";
        }
        let duration = start_time.elapsed();
        let time_elapsed = format!("{}.{1:.2} secs",
                                   duration.as_secs(),
                                   duration.subsec_nanos() / 10000000);
        if self.queue.is_empty() {
            let message = format!("{} [{}] target(s) in {}",
                                  build_type,
                                  opt_type,
                                  time_elapsed);
            cx.config.shell().status("Finished", message)?;
            Ok(())
        } else if let Some(e) = error {
            Err(e)
        } else {
            debug!("queue: {:#?}", self.queue);
            Err(internal("finished with jobs still left in the queue"))
        }
    }

    /// Executes a job in the `scope` given, pushing the spawned thread's
    /// handled onto `threads`.
    fn run(&mut self,
           key: Key<'a>,
           fresh: Freshness,
           job: Job,
           config: &Config,
           scope: &Scope<'a>) -> CargoResult<()> {
        info!("start: {:?}", key);

        self.active += 1;
        *self.counts.get_mut(key.pkg).unwrap() -= 1;

        let my_tx = self.tx.clone();
        scope.spawn(move || {
            let res = job.run(fresh, &JobState {
                tx: my_tx.clone(),
                key: key,
            });
            my_tx.send((key, Message::Finish(res))).unwrap();
        });

        // Print out some nice progress information
        self.note_working_on(config, &key, fresh)?;

        Ok(())
    }

    fn finish(&mut self, key: Key<'a>, cx: &mut Context) -> CargoResult<()> {
        if key.profile.run_custom_build && cx.show_warnings(key.pkg) {
            let output = cx.build_state.outputs.lock().unwrap();
            if let Some(output) = output.get(&(key.pkg.clone(), key.kind)) {
                for warning in output.warnings.iter() {
                    cx.config.shell().warn(warning)?;
                }
            }
        }
        let state = self.pending.get_mut(&key).unwrap();
        state.amt -= 1;
        if state.amt == 0 {
            self.queue.finish(&key, state.fresh);
        }
        Ok(())
    }

    // This isn't super trivial because we don't want to print loads and
    // loads of information to the console, but we also want to produce a
    // faithful representation of what's happening. This is somewhat nuanced
    // as a package can start compiling *very* early on because of custom
    // build commands and such.
    //
    // In general, we try to print "Compiling" for the first nontrivial task
    // run for a package, regardless of when that is. We then don't print
    // out any more information for a package after we've printed it once.
    fn note_working_on(&mut self,
                       config: &Config,
                       key: &Key<'a>,
                       fresh: Freshness) -> CargoResult<()> {
        if (self.compiled.contains(key.pkg) && !key.profile.doc) ||
            (self.documented.contains(key.pkg) && key.profile.doc) {
            return Ok(())
        }

        match fresh {
            // Any dirty stage which runs at least one command gets printed as
            // being a compiled package
            Dirty => {
                if key.profile.doc {
                    if !key.profile.test {
                        self.documented.insert(key.pkg);
                        config.shell().status("Documenting", key.pkg)?;
                    }
                } else {
                    self.compiled.insert(key.pkg);
                    config.shell().status("Compiling", key.pkg)?;
                }
            }
            Fresh if self.counts[key.pkg] == 0 => {
                self.compiled.insert(key.pkg);
                config.shell().verbose(|c| c.status("Fresh", key.pkg))?;
            }
            Fresh => {}
        }
        Ok(())
    }
}

impl<'a> Key<'a> {
    fn new(unit: &Unit<'a>) -> Key<'a> {
        Key {
            pkg: unit.pkg.package_id(),
            target: unit.target,
            profile: unit.profile,
            kind: unit.kind,
        }
    }

    fn dependencies<'cfg>(&self, cx: &Context<'a, 'cfg>)
                          -> CargoResult<Vec<Key<'a>>> {
        let unit = Unit {
            pkg: cx.get_package(self.pkg)?,
            target: self.target,
            profile: self.profile,
            kind: self.kind,
        };
        let targets = cx.dep_targets(&unit)?;
        Ok(targets.iter().filter_map(|unit| {
            // Binaries aren't actually needed to *compile* tests, just to run
            // them, so we don't include this dependency edge in the job graph.
            if self.target.is_test() && unit.target.is_bin() {
                None
            } else {
                Some(Key::new(unit))
            }
        }).collect())
    }
}

impl<'a> fmt::Debug for Key<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} => {}/{} => {:?}", self.pkg, self.target, self.profile,
               self.kind)
    }
}
<commit_msg>directly print error only if there is more than one job in the queue<commit_after>use std::collections::HashSet;
use std::collections::hash_map::HashMap;
use std::fmt;
use std::io::Write;
use std::sync::mpsc::{channel, Sender, Receiver};

use crossbeam::{self, Scope};
use term::color::YELLOW;

use core::{PackageId, Target, Profile};
use util::{Config, DependencyQueue, Fresh, Dirty, Freshness};
use util::{CargoResult, ProcessBuilder, profile, internal, human};
use {handle_error};

use super::{Context, Kind, Unit};
use super::job::Job;

/// A management structure of the entire dependency graph to compile.
///
/// This structure is backed by the `DependencyQueue` type and manages the
/// actual compilation step of each package. Packages enqueue units of work and
/// then later on the entire graph is processed and compiled.
pub struct JobQueue<'a> {
    jobs: usize,
    queue: DependencyQueue<Key<'a>, Vec<(Job, Freshness)>>,
    tx: Sender<(Key<'a>, Message)>,
    rx: Receiver<(Key<'a>, Message)>,
    active: usize,
    pending: HashMap<Key<'a>, PendingBuild>,
    compiled: HashSet<&'a PackageId>,
    documented: HashSet<&'a PackageId>,
    counts: HashMap<&'a PackageId, usize>,
    is_release: bool,
}

/// A helper structure for metadata about the state of a building package.
struct PendingBuild {
    /// Number of jobs currently active
    amt: usize,
    /// Current freshness state of this package. Any dirty target within a
    /// package will cause the entire package to become dirty.
    fresh: Freshness,
}

#[derive(Clone, Copy, Eq, PartialEq, Hash)]
struct Key<'a> {
    pkg: &'a PackageId,
    target: &'a Target,
    profile: &'a Profile,
    kind: Kind,
}

pub struct JobState<'a> {
    tx: Sender<(Key<'a>, Message)>,
    key: Key<'a>,
}

enum Message {
    Run(String),
    Stdout(String),
    Stderr(String),
    Finish(CargoResult<()>),
}

impl<'a> JobState<'a> {
    pub fn running(&self, cmd: &ProcessBuilder) {
        let _ = self.tx.send((self.key, Message::Run(cmd.to_string())));
    }

    pub fn stdout(&self, out: &str) {
        let _ = self.tx.send((self.key, Message::Stdout(out.to_string())));
    }

    pub fn stderr(&self, err: &str) {
        let _ = self.tx.send((self.key, Message::Stderr(err.to_string())));
    }
}

impl<'a> JobQueue<'a> {
    pub fn new<'cfg>(cx: &Context<'a, 'cfg>) -> JobQueue<'a> {
        let (tx, rx) = channel();
        JobQueue {
            jobs: cx.jobs() as usize,
            queue: DependencyQueue::new(),
            tx: tx,
            rx: rx,
            active: 0,
            pending: HashMap::new(),
            compiled: HashSet::new(),
            documented: HashSet::new(),
            counts: HashMap::new(),
            is_release: cx.build_config.release,
        }
    }

    pub fn enqueue<'cfg>(&mut self,
                         cx: &Context<'a, 'cfg>,
                         unit: &Unit<'a>,
                         job: Job,
                         fresh: Freshness) -> CargoResult<()> {
        let key = Key::new(unit);
        let deps = key.dependencies(cx)?;
        self.queue.queue(Fresh, key, Vec::new(), &deps).push((job, fresh));
        *self.counts.entry(key.pkg).or_insert(0) += 1;
        Ok(())
    }

    /// Execute all jobs necessary to build the dependency graph.
    ///
    /// This function will spawn off `config.jobs()` workers to build all of the
    /// necessary dependencies, in order. Freshness is propagated as far as
    /// possible along each dependency chain.
    pub fn execute(&mut self, cx: &mut Context) -> CargoResult<()> {
        let _p = profile::start("executing the job graph");

        crossbeam::scope(|scope| {
            self.drain_the_queue(cx, scope)
        })
    }

    fn drain_the_queue(&mut self, cx: &mut Context, scope: &Scope<'a>)
                       -> CargoResult<()> {
        use std::time::Instant;

        let mut queue = Vec::new();
        trace!("queue: {:#?}", self.queue);

        // Iteratively execute the entire dependency graph. Each turn of the
        // loop starts out by scheduling as much work as possible (up to the
        // maximum number of parallel jobs). A local queue is maintained
        // separately from the main dependency queue as one dequeue may actually
        // dequeue quite a bit of work (e.g. 10 binaries in one project).
        //
        // After a job has finished we update our internal state if it was
        // successful and otherwise wait for pending work to finish if it failed
        // and then immediately return.
        let mut error = None;
        let start_time = Instant::now();
        loop {
            while error.is_none() && self.active < self.jobs {
                if !queue.is_empty() {
                    let (key, job, fresh) = queue.remove(0);
                    self.run(key, fresh, job, cx.config, scope)?;
                } else if let Some((fresh, key, jobs)) = self.queue.dequeue() {
                    let total_fresh = jobs.iter().fold(fresh, |fresh, &(_, f)| {
                        f.combine(fresh)
                    });
                    self.pending.insert(key, PendingBuild {
                        amt: jobs.len(),
                        fresh: total_fresh,
                    });
                    queue.extend(jobs.into_iter().map(|(job, f)| {
                        (key, job, f.combine(fresh))
                    }));
                } else {
                    break
                }
            }
            if self.active == 0 {
                break
            }

            let (key, msg) = self.rx.recv().unwrap();

            match msg {
                Message::Run(cmd) => {
                    cx.config.shell().verbose(|c| c.status("Running", &cmd))?;
                }
                Message::Stdout(out) => {
                    if cx.config.extra_verbose() {
                        writeln!(cx.config.shell().out(), "{}", out)?;
                    }
                }
                Message::Stderr(err) => {
                    if cx.config.extra_verbose() {
                        writeln!(cx.config.shell().err(), "{}", err)?;
                    }
                }
                Message::Finish(result) => {
                    info!("end: {:?}", key);
                    self.active -= 1;
                    match result {
                        Ok(()) => self.finish(key, cx)?,
                        Err(e) => {
                            if self.active > 0 {
                                error = Some(human("build failed"));
                                handle_error(&*e, &mut *cx.config.shell());
                                cx.config.shell().say(
                                            "Build failed, waiting for other \
                                             jobs to finish...", YELLOW)?;
                            }
                            if error.is_none() {
                                error = Some(e);
                            }
                        }
                    }
                }
            }
        }

        let build_type = if self.is_release { "release" } else { "dev" };
        let profile = cx.lib_profile();
        let mut opt_type = String::from(if profile.opt_level == "0" { "unoptimized" }
                                        else { "optimized" });
        if profile.debuginfo.is_some() {
            opt_type = opt_type + " + debuginfo";
        }
        let duration = start_time.elapsed();
        let time_elapsed = format!("{}.{1:.2} secs",
                                   duration.as_secs(),
                                   duration.subsec_nanos() / 10000000);
        if self.queue.is_empty() {
            let message = format!("{} [{}] target(s) in {}",
                                  build_type,
                                  opt_type,
                                  time_elapsed);
            cx.config.shell().status("Finished", message)?;
            Ok(())
        } else if let Some(e) = error {
            Err(e)
        } else {
            debug!("queue: {:#?}", self.queue);
            Err(internal("finished with jobs still left in the queue"))
        }
    }

    /// Executes a job in the `scope` given, pushing the spawned thread's
    /// handled onto `threads`.
    fn run(&mut self,
           key: Key<'a>,
           fresh: Freshness,
           job: Job,
           config: &Config,
           scope: &Scope<'a>) -> CargoResult<()> {
        info!("start: {:?}", key);

        self.active += 1;
        *self.counts.get_mut(key.pkg).unwrap() -= 1;

        let my_tx = self.tx.clone();
        scope.spawn(move || {
            let res = job.run(fresh, &JobState {
                tx: my_tx.clone(),
                key: key,
            });
            my_tx.send((key, Message::Finish(res))).unwrap();
        });

        // Print out some nice progress information
        self.note_working_on(config, &key, fresh)?;

        Ok(())
    }

    fn finish(&mut self, key: Key<'a>, cx: &mut Context) -> CargoResult<()> {
        if key.profile.run_custom_build && cx.show_warnings(key.pkg) {
            let output = cx.build_state.outputs.lock().unwrap();
            if let Some(output) = output.get(&(key.pkg.clone(), key.kind)) {
                for warning in output.warnings.iter() {
                    cx.config.shell().warn(warning)?;
                }
            }
        }
        let state = self.pending.get_mut(&key).unwrap();
        state.amt -= 1;
        if state.amt == 0 {
            self.queue.finish(&key, state.fresh);
        }
        Ok(())
    }

    // This isn't super trivial because we don't want to print loads and
    // loads of information to the console, but we also want to produce a
    // faithful representation of what's happening. This is somewhat nuanced
    // as a package can start compiling *very* early on because of custom
    // build commands and such.
    //
    // In general, we try to print "Compiling" for the first nontrivial task
    // run for a package, regardless of when that is. We then don't print
    // out any more information for a package after we've printed it once.
    fn note_working_on(&mut self,
                       config: &Config,
                       key: &Key<'a>,
                       fresh: Freshness) -> CargoResult<()> {
        if (self.compiled.contains(key.pkg) && !key.profile.doc) ||
            (self.documented.contains(key.pkg) && key.profile.doc) {
            return Ok(())
        }

        match fresh {
            // Any dirty stage which runs at least one command gets printed as
            // being a compiled package
            Dirty => {
                if key.profile.doc {
                    if !key.profile.test {
                        self.documented.insert(key.pkg);
                        config.shell().status("Documenting", key.pkg)?;
                    }
                } else {
                    self.compiled.insert(key.pkg);
                    config.shell().status("Compiling", key.pkg)?;
                }
            }
            Fresh if self.counts[key.pkg] == 0 => {
                self.compiled.insert(key.pkg);
                config.shell().verbose(|c| c.status("Fresh", key.pkg))?;
            }
            Fresh => {}
        }
        Ok(())
    }
}

impl<'a> Key<'a> {
    fn new(unit: &Unit<'a>) -> Key<'a> {
        Key {
            pkg: unit.pkg.package_id(),
            target: unit.target,
            profile: unit.profile,
            kind: unit.kind,
        }
    }

    fn dependencies<'cfg>(&self, cx: &Context<'a, 'cfg>)
                          -> CargoResult<Vec<Key<'a>>> {
        let unit = Unit {
            pkg: cx.get_package(self.pkg)?,
            target: self.target,
            profile: self.profile,
            kind: self.kind,
        };
        let targets = cx.dep_targets(&unit)?;
        Ok(targets.iter().filter_map(|unit| {
            // Binaries aren't actually needed to *compile* tests, just to run
            // them, so we don't include this dependency edge in the job graph.
            if self.target.is_test() && unit.target.is_bin() {
                None
            } else {
                Some(Key::new(unit))
            }
        }).collect())
    }
}

impl<'a> fmt::Debug for Key<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} => {}/{} => {:?}", self.pkg, self.target, self.profile,
               self.kind)
    }
}
<|endoftext|>