<commit_before>// only-linux
// compile-flags: -Zmiri-disable-isolation

#![feature(rustc_private)]
extern crate libc;

use std::mem::MaybeUninit;
use std::ptr;
use std::thread;
use std::time::{Duration, Instant};

fn wake_nobody() {
    let futex = 0;

    // Wake 1 waiter. Expect zero waiters woken up, as nobody is waiting.
    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &futex as *const i32,
            libc::FUTEX_WAKE,
            1,
        ), 0);
    }

    // Same, but without omitting the unused arguments.
    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &futex as *const i32,
            libc::FUTEX_WAKE,
            1,
            ptr::null::<libc::timespec>(),
            0usize,
            0,
        ), 0);
    }
}

fn wake_dangling() {
    let futex = Box::new(0);
    let ptr: *const i32 = &*futex;
    drop(futex);

    // Wake 1 waiter. Expect zero waiters woken up, as nobody is waiting.
    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            ptr,
            libc::FUTEX_WAKE,
            1,
        ), 0);
    }
}

fn wait_wrong_val() {
    let futex: i32 = 123;

    // Only wait if the futex value is 456.
    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &futex as *const i32,
            libc::FUTEX_WAIT,
            456,
            ptr::null::<libc::timespec>(),
        ), -1);
        assert_eq!(*libc::__errno_location(), libc::EAGAIN);
    }
}

fn wait_timeout() {
    let start = Instant::now();

    let futex: i32 = 123;

    // Wait for 200ms, with nobody waking us up early.
    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &futex as *const i32,
            libc::FUTEX_WAIT,
            123,
            &libc::timespec {
                tv_sec: 0,
                tv_nsec: 200_000_000,
            },
        ), -1);
        assert_eq!(*libc::__errno_location(), libc::ETIMEDOUT);
    }

    assert!((200..1000).contains(&start.elapsed().as_millis()));
}

fn wait_absolute_timeout() {
    let start = Instant::now();

    // Get the current monotonic timestamp as timespec.
    let mut timeout = unsafe {
        let mut now: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
        assert_eq!(libc::clock_gettime(libc::CLOCK_MONOTONIC, now.as_mut_ptr()), 0);
        now.assume_init()
    };

    // Add 200ms.
    timeout.tv_nsec += 200_000_000;
    if timeout.tv_nsec > 1_000_000_000 {
        timeout.tv_nsec -= 1_000_000_000;
        timeout.tv_sec += 1;
    }

    let futex: i32 = 123;

    // Wait for 200ms from now, with nobody waking us up early.
    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &futex as *const i32,
            libc::FUTEX_WAIT_BITSET,
            123,
            &timeout,
            0usize,
            u32::MAX,
        ), -1);
        assert_eq!(*libc::__errno_location(), libc::ETIMEDOUT);
    }

    assert!((200..1000).contains(&start.elapsed().as_millis()));
}

fn wait_wake() {
    let start = Instant::now();

    static FUTEX: i32 = 0;

    thread::spawn(move || {
        thread::sleep(Duration::from_millis(200));
        unsafe {
            assert_eq!(libc::syscall(
                libc::SYS_futex,
                &FUTEX as *const i32,
                libc::FUTEX_WAKE,
                10, // Wake up at most 10 threads.
            ), 1); // Woken up one thread.
        }
    });

    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &FUTEX as *const i32,
            libc::FUTEX_WAIT,
            0,
            ptr::null::<libc::timespec>(),
        ), 0);
    }

    assert!((200..1000).contains(&start.elapsed().as_millis()));
}

fn wait_wake_bitset() {
    let start = Instant::now();

    static FUTEX: i32 = 0;

    thread::spawn(move || {
        thread::sleep(Duration::from_millis(200));
        unsafe {
            assert_eq!(libc::syscall(
                libc::SYS_futex,
                &FUTEX as *const i32,
                libc::FUTEX_WAKE_BITSET,
                10, // Wake up at most 10 threads.
                ptr::null::<libc::timespec>(),
                0usize,
                0b1001, // bitset
            ), 0); // Didn't match any thread.
        }
        thread::sleep(Duration::from_millis(200));
        unsafe {
            assert_eq!(libc::syscall(
                libc::SYS_futex,
                &FUTEX as *const i32,
                libc::FUTEX_WAKE_BITSET,
                10, // Wake up at most 10 threads.
                ptr::null::<libc::timespec>(),
                0usize,
                0b0110, // bitset
            ), 1); // Woken up one thread.
        }
    });

    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &FUTEX as *const i32,
            libc::FUTEX_WAIT_BITSET,
            0,
            ptr::null::<libc::timespec>(),
            0usize,
            0b0100, // bitset
        ), 0);
    }

    assert!((400..1000).contains(&start.elapsed().as_millis()));
}

fn main() {
    wake_nobody();
    wake_dangling();
    wait_wrong_val();
    wait_timeout();
    wait_absolute_timeout();
    wait_wake();
    wait_wake_bitset();
}
<commit_msg>linux-futex test: ensure we join all threads<commit_after>// only-linux
// compile-flags: -Zmiri-disable-isolation

#![feature(rustc_private)]
extern crate libc;

use std::mem::MaybeUninit;
use std::ptr;
use std::thread;
use std::time::{Duration, Instant};

fn wake_nobody() {
    let futex = 0;

    // Wake 1 waiter. Expect zero waiters woken up, as nobody is waiting.
    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &futex as *const i32,
            libc::FUTEX_WAKE,
            1,
        ), 0);
    }

    // Same, but without omitting the unused arguments.
    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &futex as *const i32,
            libc::FUTEX_WAKE,
            1,
            ptr::null::<libc::timespec>(),
            0usize,
            0,
        ), 0);
    }
}

fn wake_dangling() {
    let futex = Box::new(0);
    let ptr: *const i32 = &*futex;
    drop(futex);

    // Wake 1 waiter. Expect zero waiters woken up, as nobody is waiting.
    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            ptr,
            libc::FUTEX_WAKE,
            1,
        ), 0);
    }
}

fn wait_wrong_val() {
    let futex: i32 = 123;

    // Only wait if the futex value is 456.
    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &futex as *const i32,
            libc::FUTEX_WAIT,
            456,
            ptr::null::<libc::timespec>(),
        ), -1);
        assert_eq!(*libc::__errno_location(), libc::EAGAIN);
    }
}

fn wait_timeout() {
    let start = Instant::now();

    let futex: i32 = 123;

    // Wait for 200ms, with nobody waking us up early.
    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &futex as *const i32,
            libc::FUTEX_WAIT,
            123,
            &libc::timespec {
                tv_sec: 0,
                tv_nsec: 200_000_000,
            },
        ), -1);
        assert_eq!(*libc::__errno_location(), libc::ETIMEDOUT);
    }

    assert!((200..1000).contains(&start.elapsed().as_millis()));
}

fn wait_absolute_timeout() {
    let start = Instant::now();

    // Get the current monotonic timestamp as timespec.
    let mut timeout = unsafe {
        let mut now: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
        assert_eq!(libc::clock_gettime(libc::CLOCK_MONOTONIC, now.as_mut_ptr()), 0);
        now.assume_init()
    };

    // Add 200ms.
    timeout.tv_nsec += 200_000_000;
    if timeout.tv_nsec > 1_000_000_000 {
        timeout.tv_nsec -= 1_000_000_000;
        timeout.tv_sec += 1;
    }

    let futex: i32 = 123;

    // Wait for 200ms from now, with nobody waking us up early.
    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &futex as *const i32,
            libc::FUTEX_WAIT_BITSET,
            123,
            &timeout,
            0usize,
            u32::MAX,
        ), -1);
        assert_eq!(*libc::__errno_location(), libc::ETIMEDOUT);
    }

    assert!((200..1000).contains(&start.elapsed().as_millis()));
}

fn wait_wake() {
    let start = Instant::now();

    static FUTEX: i32 = 0;

    let t = thread::spawn(move || {
        thread::sleep(Duration::from_millis(200));
        unsafe {
            assert_eq!(libc::syscall(
                libc::SYS_futex,
                &FUTEX as *const i32,
                libc::FUTEX_WAKE,
                10, // Wake up at most 10 threads.
            ), 1); // Woken up one thread.
        }
    });

    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &FUTEX as *const i32,
            libc::FUTEX_WAIT,
            0,
            ptr::null::<libc::timespec>(),
        ), 0);
    }

    assert!((200..1000).contains(&start.elapsed().as_millis()));
    t.join().unwrap();
}

fn wait_wake_bitset() {
    let start = Instant::now();

    static FUTEX: i32 = 0;

    let t = thread::spawn(move || {
        thread::sleep(Duration::from_millis(200));
        unsafe {
            assert_eq!(libc::syscall(
                libc::SYS_futex,
                &FUTEX as *const i32,
                libc::FUTEX_WAKE_BITSET,
                10, // Wake up at most 10 threads.
                ptr::null::<libc::timespec>(),
                0usize,
                0b1001, // bitset
            ), 0); // Didn't match any thread.
        }
        thread::sleep(Duration::from_millis(200));
        unsafe {
            assert_eq!(libc::syscall(
                libc::SYS_futex,
                &FUTEX as *const i32,
                libc::FUTEX_WAKE_BITSET,
                10, // Wake up at most 10 threads.
                ptr::null::<libc::timespec>(),
                0usize,
                0b0110, // bitset
            ), 1); // Woken up one thread.
        }
    });

    unsafe {
        assert_eq!(libc::syscall(
            libc::SYS_futex,
            &FUTEX as *const i32,
            libc::FUTEX_WAIT_BITSET,
            0,
            ptr::null::<libc::timespec>(),
            0usize,
            0b0100, // bitset
        ), 0);
    }

    assert!((400..1000).contains(&start.elapsed().as_millis()));
    t.join().unwrap();
}

fn main() {
    wake_nobody();
    wake_dangling();
    wait_wrong_val();
    wait_timeout();
    wait_absolute_timeout();
    wait_wake();
    wait_wake_bitset();
}
<|endoftext|>


<commit_before>extern crate tempdir;
extern crate cc;

use std::env;

mod support;
use support::Test;

#[test]
fn main() {
    ccache();
    distcc();
    ccache_spaces();
    ccache_env_flags();
}

fn ccache() {
    let test = Test::gnu();

    env::set_var("CC", "ccache cc");
    test.gcc().file("foo.c").compile("foo");

    test.cmd(0)
        .must_have("foo.c")
        .must_not_have("ccache");
    test.cmd(1).must_have(test.td.path().join("foo.o"));
}

fn ccache_spaces() {
    let test = Test::gnu();
    test.shim("ccache");

    env::set_var("CC", "ccache        cc");
    test.gcc().file("foo.c").compile("libfoo.a");
    test.cmd(0).must_have("foo.c");
    test.cmd(1).must_have(test.td.path().join("foo.o"));
}

fn distcc() {
    let test = Test::gnu();
    test.shim("distcc");

    env::set_var("CC", "distcc cc");
    test.gcc().file("foo.c").compile("foo");

    test.cmd(0)
        .must_have("foo.c")
        .must_not_have("distcc");
    test.cmd(1).must_have(test.td.path().join("foo.o"));
}

fn ccache_env_flags() {
    use std::path::Path;
    use std::ffi::OsString;

    let test = Test::gnu();
    test.shim("ccache");

    env::set_var("CC", "ccache lol-this-is-not-a-compiler");
    let compiler = test.gcc().file("foo.c").get_compiler();
    assert_eq!(compiler.path(), Path::new("lol-this-is-not-a-compiler"));
    assert_eq!(compiler.cc_env(), OsString::from("ccache lol-this-is-not-a-compiler"));
    assert!(compiler.cflags_env().into_string().unwrap().contains("ccache") == false);
    assert!(compiler.cflags_env().into_string().unwrap().contains(" lol-this-is-not-a-compiler") == false);

    env::set_var("CC", "");
}
<commit_msg>tests for no-ccache environments<commit_after>extern crate cc;
extern crate tempdir;

use std::env;
use std::path::Path;
use std::ffi::OsString;

mod support;
use support::Test;

#[test]
fn main() {
    ccache();
    distcc();
    ccache_spaces();
    ccache_env_flags();
}

fn ccache() {
    let test = Test::gnu();

    env::set_var("CC", "ccache cc");
    let compiler = test.gcc().file("foo.c").get_compiler();

    assert_eq!(compiler.path(), Path::new("cc"));
}

fn ccache_spaces() {
    let test = Test::gnu();
    test.shim("ccache");

    env::set_var("CC", "ccache        cc");
    let compiler = test.gcc().file("foo.c").get_compiler();
    assert_eq!(compiler.path(), Path::new("cc"));
}

fn distcc() {
    let test = Test::gnu();
    test.shim("distcc");

    env::set_var("CC", "distcc cc");
    let compiler = test.gcc().file("foo.c").get_compiler();
    assert_eq!(compiler.path(), Path::new("cc"));
}

fn ccache_env_flags() {
    let test = Test::gnu();
    test.shim("ccache");

    env::set_var("CC", "ccache lol-this-is-not-a-compiler");
    let compiler = test.gcc().file("foo.c").get_compiler();
    assert_eq!(compiler.path(), Path::new("lol-this-is-not-a-compiler"));
    assert_eq!(
        compiler.cc_env(),
        OsString::from("ccache lol-this-is-not-a-compiler")
    );
    assert!(
        compiler
            .cflags_env()
            .into_string()
            .unwrap()
            .contains("ccache") == false
    );
    assert!(
        compiler
            .cflags_env()
            .into_string()
            .unwrap()
            .contains(" lol-this-is-not-a-compiler") == false
    );

    env::set_var("CC", "");
}
<|endoftext|>


<commit_before>use ahash::*;
use std::hash::{Hash, Hasher};

///Basic sanity tests of the cypto properties of aHash.
#[cfg(test)]
mod crypto {
    use crate::*;

    pub fn ahash<H: Hash>(b: H) -> u64 {
        let mut hasher = AHasher::new_with_keys(0, 0);
        b.hash(&mut hasher);
        hasher.finish()
    }

    fn assert_sufficently_different(a: u64, b: u64) {
        let flipped_bits = (a ^ b).count_ones();
        assert!(flipped_bits > 14 && flipped_bits < 50, "{:x} and {:x}: {:}", a, b, flipped_bits);
        for rotate in 0..64 {
            let flipped_bits = (a ^ (b.rotate_left(rotate))).count_ones();
            assert!(flipped_bits > 10 && flipped_bits < 54, "{:x} and {:x}: {:x}", a, b, flipped_bits);
        }
    }

    #[test]
    fn test_single_bit_flip() {
        let size = 32;
        let compare_value = ahash(0u32);
        for pos in 0..size {
            let test_value = ahash(0 ^ (1u32 << pos));
            assert_sufficently_different(compare_value, test_value);
        }
        let size = 64;
        let compare_value = ahash(0u64);
        for pos in 0..size {
            let test_value = ahash(0 ^ (1u64 << pos));
            assert_sufficently_different(compare_value, test_value);
        }
        let size = 128;
        let compare_value = ahash(0u128);
        for pos in 0..size {
            let test_value = ahash(0 ^ (1u128 << pos));
            assert_sufficently_different(compare_value, test_value);
        }
    }

    #[test]
    fn test_keys_change_output() {
        let mut a = AHasher::new_with_keys(0, 0);
        let mut b = AHasher::new_with_keys(0, 1);
        let mut c = AHasher::new_with_keys(1, 0);
        let mut d = AHasher::new_with_keys(1, 1);
        "test".hash(&mut a);
        "test".hash(&mut b);
        "test".hash(&mut c);
        "test".hash(&mut d);
        assert_sufficently_different(a.finish(), b.finish());
        assert_sufficently_different(a.finish(), c.finish());
        assert_sufficently_different(a.finish(), d.finish());
        assert_sufficently_different(b.finish(), c.finish());
        assert_sufficently_different(b.finish(), d.finish());
        assert_sufficently_different(c.finish(), d.finish());
    }

    #[test]
    fn test_finish_is_consistant() {
        let mut hasher = AHasher::new_with_keys(1, 2);
        "Foo".hash(&mut hasher);
        let a = hasher.finish();
        let b = hasher.finish();
        assert_eq!(a, b);
    }

    #[test]
    fn test_single_key_bit_flip() {
        for bit in 0..64 {
            let mut a = AHasher::new_with_keys(0, 0);
            let mut b = AHasher::new_with_keys(0, 1 << bit);
            let mut c = AHasher::new_with_keys(1 << bit, 0);
            "1234".hash(&mut a);
            "1234".hash(&mut b);
            "1234".hash(&mut c);
            assert_sufficently_different(a.finish(), b.finish());
            assert_sufficently_different(a.finish(), c.finish());
            assert_sufficently_different(b.finish(), c.finish());
            let mut a = AHasher::new_with_keys(0, 0);
            let mut b = AHasher::new_with_keys(0, 1 << bit);
            let mut c = AHasher::new_with_keys(1 << bit, 0);
            "12345678".hash(&mut a);
            "12345678".hash(&mut b);
            "12345678".hash(&mut c);
            assert_sufficently_different(a.finish(), b.finish());
            assert_sufficently_different(a.finish(), c.finish());
            assert_sufficently_different(b.finish(), c.finish());
            let mut a = AHasher::new_with_keys(0, 0);
            let mut b = AHasher::new_with_keys(0, 1 << bit);
            let mut c = AHasher::new_with_keys(1 << bit, 0);
            "1234567812345678".hash(&mut a);
            "1234567812345678".hash(&mut b);
            "1234567812345678".hash(&mut c);
            assert_sufficently_different(a.finish(), b.finish());
            assert_sufficently_different(a.finish(), c.finish());
            assert_sufficently_different(b.finish(), c.finish());
        }
    }

    #[test]
    fn test_padding_doesnot_collide() {
        for c in 0..128u8 {
            for string in ["", "1234", "12345678", "1234567812345678"].into_iter() {
                let mut short = AHasher::default();
                string.hash(&mut short);
                let value = short.finish();
                let mut string = string.to_string();
                for _ in 0..128 {
                    let mut long = AHasher::default();
                    string.push(c as char);
                    string.hash(&mut long);
                    let flipped_bits = (value ^ long.finish()).count_ones();
                    assert!(flipped_bits > 10);
                }
            }
        }
    }
}

#[cfg(test)]
mod fallback {
    use crate::*;
    use ahash::fallback::FallbackHasher;

    pub fn fallback<H: Hash>(b: H) -> u64 {
        let mut hasher = FallbackHasher::new_with_keys(0, 0);
        b.hash(&mut hasher);
        hasher.finish()
    }

    fn assert_sufficently_different(a: u64, b: u64) {
        let flipped_bits = (a ^ b).count_ones();
        assert!(flipped_bits > 14 && flipped_bits < 50, "{:x} and {:x}: {:}", a, b, flipped_bits);
        for rotate in 0..64 {
            let flipped_bits = (a ^ (b.rotate_left(rotate))).count_ones();
            assert!(flipped_bits > 10 && flipped_bits < 54, "{:x} and {:x}: {:x}", a, b, flipped_bits);
        }
    }

    #[test]
    fn test_single_bit_flip() {
        let size = 32;
        let compare_value = fallback(0u32);
        for pos in 0..size {
            let test_value = fallback(0 ^ (1u32 << pos));
            assert_sufficently_different(compare_value, test_value);
        }
        let size = 64;
        let compare_value = fallback(0u64);
        for pos in 0..size {
            let test_value = fallback(0 ^ (1u64 << pos));
            assert_sufficently_different(compare_value, test_value);
        }
        let size = 128;
        let compare_value = fallback(0u128);
        for pos in 0..size {
            let test_value = fallback(0 ^ (1u128 << pos));
            assert_sufficently_different(compare_value, test_value);
        }
    }

    #[test]
    fn test_keys_change_output() {
        let mut a = FallbackHasher::new_with_keys(0, 0);
        let mut b = FallbackHasher::new_with_keys(0, 1);
        let mut c = FallbackHasher::new_with_keys(1, 0);
        let mut d = FallbackHasher::new_with_keys(1, 1);
        "test".hash(&mut a);
        "test".hash(&mut b);
        "test".hash(&mut c);
        "test".hash(&mut d);
        assert_sufficently_different(a.finish(), b.finish());
        assert_sufficently_different(a.finish(), c.finish());
        assert_sufficently_different(a.finish(), d.finish());
        assert_sufficently_different(b.finish(), c.finish());
        assert_sufficently_different(b.finish(), d.finish());
        assert_sufficently_different(c.finish(), d.finish());
    }

    #[test]
    fn test_finish_is_consistant() {
        let mut hasher = FallbackHasher::new_with_keys(1, 2);
        "Foo".hash(&mut hasher);
        let a = hasher.finish();
        let b = hasher.finish();
        assert_eq!(a, b);
    }

    #[test]
    fn test_single_key_bit_flip() {
        for bit in 0..64 {
            let mut a = FallbackHasher::new_with_keys(0, 0);
            let mut b = FallbackHasher::new_with_keys(0, 1 << bit);
            let mut c = FallbackHasher::new_with_keys(1 << bit, 0);
            "1234".hash(&mut a);
            "1234".hash(&mut b);
            "1234".hash(&mut c);
            assert_sufficently_different(a.finish(), b.finish());
            assert_sufficently_different(a.finish(), c.finish());
            assert_sufficently_different(b.finish(), c.finish());
            let mut a = FallbackHasher::new_with_keys(0, 0);
            let mut b = FallbackHasher::new_with_keys(0, 1 << bit);
            let mut c = FallbackHasher::new_with_keys(1 << bit, 0);
            "12345678".hash(&mut a);
            "12345678".hash(&mut b);
            "12345678".hash(&mut c);
            assert_sufficently_different(a.finish(), b.finish());
            assert_sufficently_different(a.finish(), c.finish());
            assert_sufficently_different(b.finish(), c.finish());
            let mut a = FallbackHasher::new_with_keys(0, 0);
            let mut b = FallbackHasher::new_with_keys(0, 1 << bit);
            let mut c = FallbackHasher::new_with_keys(1 << bit, 0);
            "1234567812345678".hash(&mut a);
            "1234567812345678".hash(&mut b);
            "1234567812345678".hash(&mut c);
            assert_sufficently_different(a.finish(), b.finish());
            assert_sufficently_different(a.finish(), c.finish());
            assert_sufficently_different(b.finish(), c.finish());
        }
    }

    #[test]
    fn test_padding_doesnot_collide() {
        for c in 0..128u8 {
            for string in ["", "1234", "12345678", "1234567812345678"].into_iter() {
                let mut short = FallbackHasher::default();
                string.hash(&mut short);
                let value = short.finish();
                let mut string = string.to_string();
                for _ in 0..128 {
                    let mut long = FallbackHasher::default();
                    string.push(c as char);
                    string.hash(&mut long);
                    let flipped_bits = (value ^ long.finish()).count_ones();
                    assert!(flipped_bits > 10,
                            format!("Too few bits fliped {} -> {:x} vs {} -> {:x}", string, value, c, long.finish()));
                }
            }
        }
    }
}<commit_msg>Improve strength of tests<commit_after>use ahash::*;
use std::hash::{Hash, Hasher};

const BAD_KEY: u64 = 0x0123456789ABCDEF;

///Basic sanity tests of the cypto properties of aHash.
#[cfg(test)]
mod crypto {
    use crate::*;

    pub fn ahash<H: Hash>(b: H) -> u64 {
        let mut hasher = AHasher::new_with_keys(BAD_KEY, BAD_KEY);
        b.hash(&mut hasher);
        hasher.finish()
    }

    #[test]
    fn test_single_bit_flip() {
        let size = 32;
        let compare_value = ahash(0u32);
        for pos in 0..size {
            let test_value = ahash(0 ^ (1u32 << pos));
            assert_sufficiently_different(compare_value, test_value);
        }
        let size = 64;
        let compare_value = ahash(0u64);
        for pos in 0..size {
            let test_value = ahash(0 ^ (1u64 << pos));
            assert_sufficiently_different(compare_value, test_value);
        }
        let size = 128;
        let compare_value = ahash(0u128);
        for pos in 0..size {
            let test_value = ahash(0 ^ (1u128 << pos));
            assert_sufficiently_different(compare_value, test_value);
        }
    }

    #[test]
    fn test_keys_change_output() {
        let mut a = AHasher::new_with_keys(0, 0);
        let mut b = AHasher::new_with_keys(0, 1);
        let mut c = AHasher::new_with_keys(1, 0);
        let mut d = AHasher::new_with_keys(1, 1);
        "test".hash(&mut a);
        "test".hash(&mut b);
        "test".hash(&mut c);
        "test".hash(&mut d);
        assert_sufficiently_different(a.finish(), b.finish());
        assert_sufficiently_different(a.finish(), c.finish());
        assert_sufficiently_different(a.finish(), d.finish());
        assert_sufficiently_different(b.finish(), c.finish());
        assert_sufficiently_different(b.finish(), d.finish());
        assert_sufficiently_different(c.finish(), d.finish());
    }

    #[test]
    fn test_finish_is_consistant() {
        let mut hasher = AHasher::new_with_keys(1, 2);
        "Foo".hash(&mut hasher);
        let a = hasher.finish();
        let b = hasher.finish();
        assert_eq!(a, b);
    }

    #[test]
    fn test_single_key_bit_flip() {
        for bit in 0..64 {
            let mut a = AHasher::new_with_keys(0, 0);
            let mut b = AHasher::new_with_keys(0, 1 << bit);
            let mut c = AHasher::new_with_keys(1 << bit, 0);
            "1234".hash(&mut a);
            "1234".hash(&mut b);
            "1234".hash(&mut c);
            assert_sufficiently_different(a.finish(), b.finish());
            assert_sufficiently_different(a.finish(), c.finish());
            assert_sufficiently_different(b.finish(), c.finish());
            let mut a = AHasher::new_with_keys(0, 0);
            let mut b = AHasher::new_with_keys(0, 1 << bit);
            let mut c = AHasher::new_with_keys(1 << bit, 0);
            "12345678".hash(&mut a);
            "12345678".hash(&mut b);
            "12345678".hash(&mut c);
            assert_sufficiently_different(a.finish(), b.finish());
            assert_sufficiently_different(a.finish(), c.finish());
            assert_sufficiently_different(b.finish(), c.finish());
            let mut a = AHasher::new_with_keys(0, 0);
            let mut b = AHasher::new_with_keys(0, 1 << bit);
            let mut c = AHasher::new_with_keys(1 << bit, 0);
            "1234567812345678".hash(&mut a);
            "1234567812345678".hash(&mut b);
            "1234567812345678".hash(&mut c);
            assert_sufficiently_different(a.finish(), b.finish());
            assert_sufficiently_different(a.finish(), c.finish());
            assert_sufficiently_different(b.finish(), c.finish());
        }
    }

    #[test]
    fn test_padding_doesnot_collide() {
        for c in 0..128u8 {
            for string in ["", "1234", "12345678", "1234567812345678"].into_iter() {
                let mut short = AHasher::default();
                string.hash(&mut short);
                let value = short.finish();
                let mut string = string.to_string();
                for num in 1..=128 {
                    let mut long = AHasher::default();
                    string.push(c as char);
                    string.hash(&mut long);
                    let same_bytes = count_same_bytes(value, long.finish());
                    assert!(same_bytes <= 2, format!("{} bytes of {} -> {:x} vs {:x}", num, c, value, long.finish()));
                    let flipped_bits = (value ^ long.finish()).count_ones();
                    assert!(flipped_bits > 10);
                }
            }
        }
    }
}

fn assert_sufficiently_different(a: u64, b: u64) {
    let same_byte_count = count_same_bytes(a, b);
    assert!(same_byte_count <= 1);
    let flipped_bits = (a ^ b).count_ones();
    assert!(flipped_bits > 18 && flipped_bits < 48, "{:x} and {:x}: {:}", a, b, flipped_bits);
    for rotate in 0..64 {
        let flipped_bits2 = (a ^ (b.rotate_left(rotate))).count_ones();
        assert!(flipped_bits2 > 14 && flipped_bits2 < 50, "{:x} and {:x}: {:}", a, b.rotate_left(rotate), flipped_bits2);
    }
}

fn count_same_bytes(a: u64, b: u64) -> i32 {
    let mut same_byte_count = 0;
    for byte in 0..8 {
        let ba = a >> 8 * byte as u8;
        let bb = b >> 8 * byte as u8;
        if ba == bb {
            same_byte_count += 1;
        }
    }
    same_byte_count
}

#[cfg(test)]
mod fallback {
    use crate::*;
    use ahash::fallback::FallbackHasher;

    pub fn fallback<H: Hash>(b: H) -> u64 {
        let mut hasher = FallbackHasher::new_with_keys(BAD_KEY, BAD_KEY);
        b.hash(&mut hasher);
        hasher.finish()
    }

    #[test]
    fn test_single_bit_flip() {
        let size = 32;
        let compare_value = fallback(0u32);
        for pos in 0..size {
            let test_value = fallback(0 ^ (1u32 << pos));
            assert_sufficiently_different(compare_value, test_value);
        }
        let size = 64;
        let compare_value = fallback(0u64);
        for pos in 0..size {
            let test_value = fallback(0 ^ (1u64 << pos));
            assert_sufficiently_different(compare_value, test_value);
        }
        let size = 128;
        let compare_value = fallback(0u128);
        for pos in 0..size {
            let test_value = fallback(0 ^ (1u128 << pos));
            assert_sufficiently_different(compare_value, test_value);
        }
    }

    #[test]
    fn test_keys_change_output() {
        let mut a = FallbackHasher::new_with_keys(0, 0);
        let mut b = FallbackHasher::new_with_keys(0, 1);
        let mut c = FallbackHasher::new_with_keys(1, 0);
        let mut d = FallbackHasher::new_with_keys(1, 1);
        "test".hash(&mut a);
        "test".hash(&mut b);
        "test".hash(&mut c);
        "test".hash(&mut d);
        assert_sufficiently_different(a.finish(), b.finish());
        assert_sufficiently_different(a.finish(), c.finish());
        assert_sufficiently_different(a.finish(), d.finish());
        assert_sufficiently_different(b.finish(), c.finish());
        assert_sufficiently_different(b.finish(), d.finish());
        assert_sufficiently_different(c.finish(), d.finish());
    }

    #[test]
    fn test_finish_is_consistant() {
        let mut hasher = FallbackHasher::new_with_keys(1, 2);
        "Foo".hash(&mut hasher);
        let a = hasher.finish();
        let b = hasher.finish();
        assert_eq!(a, b);
    }

    #[test]
    fn test_single_key_bit_flip() {
        for bit in 0..64 {
            let mut a = FallbackHasher::new_with_keys(0, 0);
            let mut b = FallbackHasher::new_with_keys(0, 1 << bit);
            let mut c = FallbackHasher::new_with_keys(1 << bit, 0);
            "1234".hash(&mut a);
            "1234".hash(&mut b);
            "1234".hash(&mut c);
            assert_sufficiently_different(a.finish(), b.finish());
            assert_sufficiently_different(a.finish(), c.finish());
            assert_sufficiently_different(b.finish(), c.finish());
            let mut a = FallbackHasher::new_with_keys(0, 0);
            let mut b = FallbackHasher::new_with_keys(0, 1 << bit);
            let mut c = FallbackHasher::new_with_keys(1 << bit, 0);
            "12345678".hash(&mut a);
            "12345678".hash(&mut b);
            "12345678".hash(&mut c);
            assert_sufficiently_different(a.finish(), b.finish());
            assert_sufficiently_different(a.finish(), c.finish());
            assert_sufficiently_different(b.finish(), c.finish());
            let mut a = FallbackHasher::new_with_keys(0, 0);
            let mut b = FallbackHasher::new_with_keys(0, 1 << bit);
            let mut c = FallbackHasher::new_with_keys(1 << bit, 0);
            "1234567812345678".hash(&mut a);
            "1234567812345678".hash(&mut b);
            "1234567812345678".hash(&mut c);
            assert_sufficiently_different(a.finish(), b.finish());
            assert_sufficiently_different(a.finish(), c.finish());
            assert_sufficiently_different(b.finish(), c.finish());
        }
    }

    #[test]
    fn test_padding_doesnot_collide() {
        for c in 0..128u8 {
            for string in ["", "1234", "12345678", "1234567812345678"].into_iter() {
                let mut short = FallbackHasher::new_with_keys(BAD_KEY, BAD_KEY);
                string.hash(&mut short);
                let value = short.finish();
                let mut string = string.to_string();
                for num in 1..=128 {
                    let mut long = FallbackHasher::new_with_keys(BAD_KEY, BAD_KEY);
                    string.push(c as char);
                    string.hash(&mut long);
                    let same_bytes = count_same_bytes(value, long.finish());
                    assert!(same_bytes <= 2, format!("{} bytes of {} -> {:x} vs {:x}", num, c, value, long.finish()));
                    let flipped_bits = (value ^ long.finish()).count_ones();
                    assert!(flipped_bits > 10,
                            format!("Too few bits fliped {} -> {:x} vs {} -> {:x}", string, value, c, long.finish()));
                }
            }
        }
    }
}<|endoftext|>


<commit_before>extern crate pandoc;

use std::path::PathBuf;

#[test]
fn creation() {
    use pandoc::PandocOption::*;
    use pandoc::OutputKind;
    let mut pandoc = pandoc::new();

    pandoc.add_input("cake");
    pandoc.set_output(OutputKind::File(String::from("lie")));
    pandoc.set_chapters();
    pandoc.set_number_sections();
    pandoc.set_latex_template("template.tex");
    pandoc.set_output_format(pandoc::OutputFormat::Beamer);
    pandoc.add_latex_path_hint("D:\\texlive\\2015\\bin\\win32");
    pandoc.set_slide_level(3);
    pandoc.set_toc();
    pandoc.add_option(Strict);
    pandoc.add_option(IndentedCodeClasses("cake".to_string()));
    let path = PathBuf::new();
    pandoc.add_option(Filter(path));
}
<commit_msg>Adjust test to new API<commit_after>extern crate pandoc;

use std::path::PathBuf;

#[test]
fn creation() {
    use pandoc::PandocOption::*;
    use pandoc::OutputKind;
    let mut pandoc = pandoc::new();

    pandoc.add_input("cake");
    pandoc.set_output(OutputKind::File(String::from("lie")));
    pandoc.set_chapters();
    pandoc.set_number_sections();
    pandoc.set_latex_template("template.tex");
    pandoc.set_output_format(pandoc::OutputFormat::Beamer, Vec::new());
    pandoc.add_latex_path_hint("D:\\texlive\\2015\\bin\\win32");
    pandoc.set_slide_level(3);
    pandoc.set_toc();
    pandoc.add_option(Strict);
    pandoc.add_option(IndentedCodeClasses("cake".to_string()));
    let path = PathBuf::new();
    pandoc.add_option(Filter(path));
}
<|endoftext|>


<commit_before>extern crate neli;

use std::error::Error;

use neli::Nl;
use neli::consts;
use neli::nl::Nlmsghdr;
use neli::genl::Genlmsghdr;
use neli::nlattr::Nlattr;

pub fn main() -> Result<(), Box<Error>> {
    let attrs = vec![Nlattr::new(None, 1, vec![Nlattr::new(None, 1, "this_family")]),
                     Nlattr::new(None, 2, vec![Nlattr::new(None, 1, "that_family")])];
    let genlmsg = Genlmsghdr::new(consts::CtrlCmd::Getfamily, 2, attrs)?;
    let nlmsg = Nlmsghdr::new(None, consts::Nlmsg::Noop, vec![consts::NlmF::Request], None, None,
                              genlmsg);
    let mut buffer = neli::StreamWriteBuffer::new_growable(Some(nlmsg.asize()));
    nlmsg.serialize(&mut buffer)?;
    println!("{:?}", buffer.as_ref());
    Ok(())
}
<commit_msg>Fix warning in example<commit_after>extern crate neli;

use std::error::Error;

use neli::Nl;
use neli::consts;
use neli::nl::Nlmsghdr;
use neli::genl::Genlmsghdr;
use neli::nlattr::Nlattr;

pub fn main() -> Result<(), Box<dyn Error>> {
    let attrs = vec![Nlattr::new(None, 1, vec![Nlattr::new(None, 1, "this_family")]),
                     Nlattr::new(None, 2, vec![Nlattr::new(None, 1, "that_family")])];
    let genlmsg = Genlmsghdr::new(consts::CtrlCmd::Getfamily, 2, attrs)?;
    let nlmsg = Nlmsghdr::new(None, consts::Nlmsg::Noop, vec![consts::NlmF::Request], None, None,
                              genlmsg);
    let mut buffer = neli::StreamWriteBuffer::new_growable(Some(nlmsg.asize()));
    nlmsg.serialize(&mut buffer)?;
    println!("{:?}", buffer.as_ref());
    Ok(())
}
<|endoftext|>


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

//! `Transaction` related types.

use std::borrow::Cow;

use serde_json::Value;

use messages::Message;
use storage::{Fork, StorageValue};
use crypto::Hash;

static MAX_RESERVED_VALUE: u16 = ::std::u8::MAX as u16;

/// A trait that describes transaction processing rules (a group of sequential operations
/// with the Exonum storage) for the given `Message`.
pub trait Transaction: Message + 'static {
    /// Verifies the transaction, which includes the message signature verification and other
    /// specific internal constraints. verify is intended to check the internal consistency of
    /// a transaction; it has no access to the blockchain state.
    /// If a transaction fails verify, it is considered incorrect and cannot be included into
    /// any correct block proposal. Incorrect transactions are never included into the blockchain.
    ///
    /// *This method should not use external data, that is, it must be a pure function.*
    fn verify(&self) -> bool;

    /// Takes the current blockchain state via `fork` and can modify it if certain conditions
    /// are met.
    ///
    /// # Notes
    ///
    /// - When programming `execute`, you should perform state-related checks before any changes
    /// to the state and return early if these checks fail.
    /// - If the execute method of a transaction raises a `panic`, the changes made by the
    /// transactions are discarded, but the transaction itself is still considered committed.
    /// - A transaction execution status (see `ExecutionStatus` for the details) is stored in the
    /// blockchain and can be accessed through api.
    /// - A transaction is considered failed if it made no changes to the storage, but its execution
    /// status can be set explicitly (see `ExecutionContext` for the details).
    fn execute(&self, context: &mut ExecutionContext);

    /// Returns the useful information about the transaction in the JSON format. The returned value
    /// is used to fill the [`TxInfo.content`] field in [the blockchain explorer][explorer].
    ///
    /// # Notes
    ///
    /// The default implementation returns `null`. For transactions defined with
    /// the [`message!`] macro, you may redefine `info()` as
    ///
    /// ```
    /// # #[macro_use] extern crate exonum;
    /// extern crate serde_json;
    /// # use exonum::blockchain::Transaction;
    /// # use exonum::storage::Fork;
    ///
    /// message! {
    ///     struct MyTransaction {
    ///         // Transaction definition...
    /// #       const TYPE = 1;
    /// #       const ID = 1;
    /// #       const SIZE = 8;
    /// #       field foo: u64 [0 => 8]
    ///     }
    /// }
    ///
    /// impl Transaction for MyTransaction {
    ///     // Other methods...
    /// #   fn verify(&self) -> bool { true }
    /// #   fn execute(&self, _: &mut Fork) -> u8 { 0 }
    ///
    ///     fn info(&self) -> serde_json::Value {
    ///         serde_json::to_value(self).expect("Cannot serialize transaction to JSON")
    ///     }
    /// }
    /// # fn main() { }
    /// ```
    ///
    /// [`TxInfo.content`]: ../explorer/struct.TxInfo.html#structfield.content
    /// [explorer]: ../explorer/index.html
    /// [`message!`]: ../macro.message.html
    fn info(&self) -> Value {
        Value::Null
    }
}

/// Execution status of the transaction.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum ExecutionStatus {
    /// Successful transaction execution.
    Succeeded,
    /// Panic occurred during transaction execution.
    Panic,
    /// General failure (unspecified reason).
    Failed,
    /// User defined execution status. Can have different meanings for different transactions and
    /// services.
    Custom(u8),
}

/// `Transaction`'s execution context.
#[derive(Debug)]
pub struct ExecutionContext<'a> {
    fork: &'a mut Fork,
    status: Option<ExecutionStatus>,
}

impl<'a> ExecutionContext<'a> {
    /// Creates a new `ExecutionContext` instance.
    pub fn new(fork: &'a mut Fork) -> Self {
        Self { fork, status: None }
    }

    /// Returns execution status consuming `ExecutionContext`.
    pub fn into_status(self) -> ExecutionStatus {
        match self.status {
            Some(val) => val,
            None => {
                // TODO: FIXME.
                ExecutionStatus::Succeeded
            }
        }
    }

    /// Returns reference to the `Fork`.
    pub fn fork(&mut self) -> &mut Fork {
        self.fork
    }

    /// Sets `Transaction`'s execution status. See `ExecutionStatus` for the details.
    pub fn set_execution_status(&mut self, status: ExecutionStatus) {
        self.status = Some(status);
    }
}

impl<'a, T: Transaction> From<T> for Box<Transaction + 'a> {
    fn from(tx: T) -> Self {
        Box::new(tx) as Box<Transaction>
    }
}

impl StorageValue for ExecutionStatus {
    fn hash(&self) -> Hash {
        u16::hash(&from_status(*self))
    }

    fn into_bytes(self) -> Vec<u8> {
        u16::into_bytes(from_status(self))
    }

    fn from_bytes(value: Cow<[u8]>) -> Self {
        to_status(u16::from_bytes(value))
    }
}

fn from_status(status: ExecutionStatus) -> u16 {
    match status {
        ExecutionStatus::Succeeded => 0,
        ExecutionStatus::Panic => 1,
        ExecutionStatus::Failed => 2,
        ExecutionStatus::Custom(value) => u16::from(value) + MAX_RESERVED_VALUE,
    }
}

fn to_status(value: u16) -> ExecutionStatus {
    match value {
        0 => ExecutionStatus::Succeeded,
        1 => ExecutionStatus::Panic,
        2 => ExecutionStatus::Failed,
        val => {
            assert!(
                val > MAX_RESERVED_VALUE,
                "Invalid ExecutionStatus value: {}",
                val
            );
            ExecutionStatus::Custom((val - MAX_RESERVED_VALUE) as u8)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use storage::{Database, MemoryDB, ListIndex};

    #[test]
    fn execution_status_round_trip() {
        let statuses = [
            ExecutionStatus::Succeeded,
            ExecutionStatus::Panic,
            ExecutionStatus::Failed,
            ExecutionStatus::Custom(0),
            ExecutionStatus::Custom(1),
            ExecutionStatus::Custom(100),
            ExecutionStatus::Custom(255),
        ];

        for status in &statuses {
            let bytes = status.clone().into_bytes();
            let new_status = ExecutionStatus::from_bytes(&bytes);

            assert_eq!(status, new_status);
        }
    }

    #[test]
    fn implicit_execution_status() {
        let db = MemoryDB::new();
        let mut fork = db.fork();

        let mut context = ExecutionContext::new(&mut fork);
        assert_eq!(ExecutionStatus::Failed, context.into_status());

        let mut context = ExecutionContext::new(&mut fork);
        let mut index = ListIndex("test", context.fork());
        index.push(1u8);
        assert_eq!(ExecutionStatus::Succeeded, context.into_status());
    }
}
<commit_msg>Determine execution status from patch<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! `Transaction` related types.

use std::borrow::Cow;

use serde_json::Value;

use messages::Message;
use storage::{Fork, StorageValue};
use crypto::Hash;

static MAX_RESERVED_VALUE: u16 = ::std::u8::MAX as u16;

/// A trait that describes transaction processing rules (a group of sequential operations
/// with the Exonum storage) for the given `Message`.
pub trait Transaction: Message + 'static {
    /// Verifies the transaction, which includes the message signature verification and other
    /// specific internal constraints. verify is intended to check the internal consistency of
    /// a transaction; it has no access to the blockchain state.
    /// If a transaction fails verify, it is considered incorrect and cannot be included into
    /// any correct block proposal. Incorrect transactions are never included into the blockchain.
    ///
    /// *This method should not use external data, that is, it must be a pure function.*
    fn verify(&self) -> bool;

    /// Takes the current blockchain state via `fork` and can modify it if certain conditions
    /// are met.
    ///
    /// # Notes
    ///
    /// - When programming `execute`, you should perform state-related checks before any changes
    /// to the state and return early if these checks fail.
    /// - If the execute method of a transaction raises a `panic`, the changes made by the
    /// transactions are discarded, but the transaction itself is still considered committed.
    /// - A transaction execution status (see `ExecutionStatus` for the details) is stored in the
    /// blockchain and can be accessed through api.
    /// - A transaction is considered failed if it made no changes to the storage, but its execution
    /// status can be set explicitly (see `ExecutionContext` for the details).
    fn execute(&self, context: &mut ExecutionContext);

    /// Returns the useful information about the transaction in the JSON format. The returned value
    /// is used to fill the [`TxInfo.content`] field in [the blockchain explorer][explorer].
    ///
    /// # Notes
    ///
    /// The default implementation returns `null`. For transactions defined with
    /// the [`message!`] macro, you may redefine `info()` as
    ///
    /// ```
    /// # #[macro_use] extern crate exonum;
    /// extern crate serde_json;
    /// # use exonum::blockchain::Transaction;
    /// # use exonum::storage::Fork;
    ///
    /// message! {
    ///     struct MyTransaction {
    ///         // Transaction definition...
    /// #       const TYPE = 1;
    /// #       const ID = 1;
    /// #       const SIZE = 8;
    /// #       field foo: u64 [0 => 8]
    ///     }
    /// }
    ///
    /// impl Transaction for MyTransaction {
    ///     // Other methods...
    /// #   fn verify(&self) -> bool { true }
    /// #   fn execute(&self, _: &mut Fork) -> u8 { 0 }
    ///
    ///     fn info(&self) -> serde_json::Value {
    ///         serde_json::to_value(self).expect("Cannot serialize transaction to JSON")
    ///     }
    /// }
    /// # fn main() { }
    /// ```
    ///
    /// [`TxInfo.content`]: ../explorer/struct.TxInfo.html#structfield.content
    /// [explorer]: ../explorer/index.html
    /// [`message!`]: ../macro.message.html
    fn info(&self) -> Value {
        Value::Null
    }
}

/// Execution status of the transaction.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum ExecutionStatus {
    /// Successful transaction execution.
    Succeeded,
    /// Panic occurred during transaction execution.
    Panic,
    /// General failure (unspecified reason).
    Failed,
    /// User defined execution status. Can have different meanings for different transactions and
    /// services.
    Custom(u8),
}

/// `Transaction`'s execution context.
#[derive(Debug)]
pub struct ExecutionContext<'a> {
    fork: &'a mut Fork,
    status: Option<ExecutionStatus>,
    changes_number: usize,
}

impl<'a> ExecutionContext<'a> {
    /// Creates a new `ExecutionContext` instance.
    pub fn new(fork: &'a mut Fork) -> Self {
        Self { changes_number: fork.patch().len(), fork, status: None, }
    }

    /// Returns execution status consuming `ExecutionContext`.
    pub fn into_status(self) -> ExecutionStatus {
        match self.status {
            Some(val) => val,
            None => {
                if self.fork.patch().len() > self.changes_number {
                    ExecutionStatus::Succeeded
                } else {
                    ExecutionStatus::Failed
                }
            }
        }
    }

    /// Returns reference to the `Fork`.
    pub fn fork(&mut self) -> &mut Fork {
        self.fork
    }

    /// Sets `Transaction`'s execution status. See `ExecutionStatus` for the details.
    pub fn set_execution_status(&mut self, status: ExecutionStatus) {
        self.status = Some(status);
    }
}

impl<'a, T: Transaction> From<T> for Box<Transaction + 'a> {
    fn from(tx: T) -> Self {
        Box::new(tx) as Box<Transaction>
    }
}

impl StorageValue for ExecutionStatus {
    fn hash(&self) -> Hash {
        u16::hash(&from_status(*self))
    }

    fn into_bytes(self) -> Vec<u8> {
        u16::into_bytes(from_status(self))
    }

    fn from_bytes(value: Cow<[u8]>) -> Self {
        to_status(u16::from_bytes(value))
    }
}

fn from_status(status: ExecutionStatus) -> u16 {
    match status {
        ExecutionStatus::Succeeded => 0,
        ExecutionStatus::Panic => 1,
        ExecutionStatus::Failed => 2,
        ExecutionStatus::Custom(value) => u16::from(value) + MAX_RESERVED_VALUE,
    }
}

fn to_status(value: u16) -> ExecutionStatus {
    match value {
        0 => ExecutionStatus::Succeeded,
        1 => ExecutionStatus::Panic,
        2 => ExecutionStatus::Failed,
        val => {
            assert!(
                val > MAX_RESERVED_VALUE,
                "Invalid ExecutionStatus value: {}",
                val
            );
            ExecutionStatus::Custom((val - MAX_RESERVED_VALUE) as u8)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use storage::{Database, MemoryDB, ListIndex};

    #[test]
    fn execution_status_round_trip() {
        let statuses = [
            ExecutionStatus::Succeeded,
            ExecutionStatus::Panic,
            ExecutionStatus::Failed,
            ExecutionStatus::Custom(0),
            ExecutionStatus::Custom(1),
            ExecutionStatus::Custom(100),
            ExecutionStatus::Custom(255),
        ];

        for status in &statuses {
            let bytes = status.clone().into_bytes();
            let new_status = ExecutionStatus::from_bytes(&bytes);

            assert_eq!(status, new_status);
        }
    }

    #[test]
    fn implicit_execution_status() {
        let db = MemoryDB::new();
        let mut fork = db.fork();

        let mut context = ExecutionContext::new(&mut fork);
        assert_eq!(ExecutionStatus::Failed, context.into_status());

        let mut context = ExecutionContext::new(&mut fork);
        let mut index = ListIndex("test", context.fork());
        index.push(1u8);
        assert_eq!(ExecutionStatus::Succeeded, context.into_status());
    }
}
<|endoftext|>


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

use super::*;
use failure::Error;
use kubos_app::query;

pub fn apps_test() -> Result<(), Error> {
    let mut passed = 0;
    let mut failed = 0;

    match get_apps() {
        Ok(()) => passed += 1,
        Err(_) => failed += 1,
    }

    info!("Applications Service Test Results: Passed - {}, Failed - {}", passed, failed);

    Ok(())
}

fn get_apps() -> Result<(), Error> {
    info!("Querying for active applications");

    let request = r#"{
        apps {
            active,
            app {
                name,
                version,
                author
            }
        }
    }"#;

    match query(
        &ServiceConfig::new("app-service")?,
        request,
        Some(Duration::from_secs(1)),
    ) {
        Ok(msg) => {
            info!("App query result: {:?}", msg);
            Ok(())
        }
        Err(err) => {
            error!("App service query failed: {}", err);
            bail!("App service query failed")
        }
    }
}
<commit_msg>Updating app service query<commit_after>/*
 * Copyright (C) 2018 Kubos Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use super::*;
use failure::Error;
use kubos_app::query;

pub fn apps_test() -> Result<(), Error> {
    let mut passed = 0;
    let mut failed = 0;

    match get_apps() {
        Ok(()) => passed += 1,
        Err(_) => failed += 1,
    }

    info!("Applications Service Test Results: Passed - {}, Failed - {}", passed, failed);

    Ok(())
}

fn get_apps() -> Result<(), Error> {
    info!("Querying for active applications");

    let request = r#"{
        registeredApps {
            active,
            app {
                name,
                version,
                author
            }
        },
        appStatus {
            name,
            version,
            runLevel,
            startTime,
            running
        }
    }"#;

    match query(
        &ServiceConfig::new("app-service")?,
        request,
        Some(Duration::from_secs(1)),
    ) {
        Ok(msg) => {
            info!("App query result: {:?}", msg);
            Ok(())
        }
        Err(err) => {
            error!("App service query failed: {}", err);
            bail!("App service query failed")
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Some crumminess to make sure we link correctly

#[cfg(target_os = "linux")]
#[link(name = "azure")]
#[link(name = "stdc++")]
#[link(name = "skia")]
#[link(name = "fontconfig")]
#[link(name = "X11")]
extern { }

#[cfg(target_os = "android")]
#[link(name = "azure")]
#[link(name = "stdc++")]
#[link(name = "skia")]
#[link(name = "expat")]
#[link(name = "fontconfig")]
#[link(name = "EGL")]
extern { }

#[cfg(target_os = "macos")]
#[link(name = "azure")]
#[link(name = "stdc++")]
#[link(name = "skia")]
#[link(name = "objc")]
#[link(name = "IOSurface", kind = "framework")]
#[link(name = "OpenGL", kind = "framework")]
#[link(name = "Foundation", kind = "framework")]
#[link(name = "QuartzCore", kind = "framework")]
#[link(name = "ApplicationServices", kind = "framework")]
extern { }
<commit_msg>Link expat on Linux (needed by fontconfig)<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Some crumminess to make sure we link correctly

#[cfg(target_os = "linux")]
#[link(name = "azure")]
#[link(name = "stdc++")]
#[link(name = "skia")]
#[link(name = "expat")]
#[link(name = "fontconfig")]
#[link(name = "X11")]
extern { }

#[cfg(target_os = "android")]
#[link(name = "azure")]
#[link(name = "stdc++")]
#[link(name = "skia")]
#[link(name = "expat")]
#[link(name = "fontconfig")]
#[link(name = "EGL")]
extern { }

#[cfg(target_os = "macos")]
#[link(name = "azure")]
#[link(name = "stdc++")]
#[link(name = "skia")]
#[link(name = "objc")]
#[link(name = "IOSurface", kind = "framework")]
#[link(name = "OpenGL", kind = "framework")]
#[link(name = "Foundation", kind = "framework")]
#[link(name = "QuartzCore", kind = "framework")]
#[link(name = "ApplicationServices", kind = "framework")]
extern { }
<|endoftext|>


<commit_before>extern mod std;
use std::hashmap::HashMap;
use sexpr;

// A very simple LISP-like language
// Globally scoped, no closures

/// Our value types
#[deriving(Clone)]
pub enum LispValue {
	List(~[LispValue]),
	Atom(~str),
	Str(~str),
	Num(float),
	Fn(~[~str], ~LispValue), // args, body
	// XXX: we need the symbol table to be a @-ptr
	// otherwise we can't mutate it. &-ptrs give lifetime
	// headaches, and ~-ptrs give move headaches.
	BIF(~str, ~[~str], extern fn(@mut HashMap<~str, ~LispValue>, ~[~LispValue])->~LispValue) // built-in function (args, closure)
}

// XXX: this is ugly but it won't automatically derive Eq because of the extern fn
impl Eq for LispValue {
	fn eq(&self, other: &LispValue) -> bool {
		match (self.clone(), other.clone()) {
			(BIF(ref x, _, _), BIF(ref y, _, _)) if *x == *y => true,
			(Str(ref x), Str(ref y)) if *x == *y => true,
			(Num(ref x), Num(ref y)) if *x == *y => true,
			(Atom(ref x), Atom(ref y)) if *x == *y => true,
			(List(ref x), List(ref y)) if *x == *y => true,
			(Fn(ref x, ref x2), Fn(ref y, ref y2)) if *x == *y && *x2 == *y2 => true,
			_ => false
		}
	}
}

fn from_sexpr(sexpr: &sexpr::Value) -> ~LispValue {
	match *sexpr {
		sexpr::List(ref v) => ~List(v.map(|x| *from_sexpr(x))),
		sexpr::Num(v) => ~Num(v),
		sexpr::Str(ref v) => ~Str(v.clone()),
		sexpr::Atom(ref v) => ~Atom(v.clone())
	}
}

/// The type of the global symbol table (string to a value mapping).
type SymbolTable = HashMap<~str, ~LispValue>;

/// Creates a new symbol table and returns it
pub fn new_symt() -> SymbolTable {
	HashMap::new()
}

/// Binds a symbol in the symbol table. Replaces if it already exists.
pub fn bind(symt: @mut SymbolTable, name: ~str, value: ~LispValue) {
	symt.insert(name, value);
}

/// Look up a symbol in the symbol table. Fails if not found.
pub fn lookup(symt: @mut SymbolTable, name: ~str) -> ~LispValue {
	match symt.find(&name) {
		Some(v) => v.clone(),
		None => fail!("couldn't find symbol: %s", name)
	}
}

fn id_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue { v[0] }

/// Initializes standard library functions
pub fn init_std(symt: @mut SymbolTable) {
	bind(symt, ~"id", ~BIF(~"id", ~[~"x"], id_));
}

fn apply(symt: @mut SymbolTable, f: ~LispValue, args: ~[~LispValue]) -> ~LispValue {
	match *f {
		BIF(name, fnargs, bif) => {
			// apply built-in function
			if fnargs.len() != args.len() {
				fail!("function '%s' requires %u arguments, but it received %u arguments",
					name, fnargs.len(), args.len())
			}

			bif(symt, args)
		}

		_ => fail!("apply: need function")
	}
}

/// Evaluates an s-expression and returns a value.
pub fn eval(symt: @mut SymbolTable, input: sexpr::Value) -> ~LispValue {
	match input {
		sexpr::List(v) => {
			if(v.len() == 0) {
				fail!("eval given empty list")
			}

			// XXX: If we don't clone, the `match` partially moves v,
			// so we can't use it in the match arms.
			let v_ = v.clone();

			// evaluate a list as a function call
			match v[0] {
				sexpr::Atom(sym) => {
					let f = lookup(symt, sym);
					let args = v_.slice(1, v_.len());
					let xargs = args.map(|x| eval(symt, x.clone())); // eval'd args
					apply(symt, f, xargs)
				}
				_ => fail!("function calls take an atom"),
			}

		}
		_ => from_sexpr(&input) // return non-list values as they are
	}
}

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

	fn read(input: &str) -> sexpr::Value {
		from_str(input).unwrap()
	}

	#[test]
	fn test_eval() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("123")), ~Num(123.0));
		assert_eq!(eval(symt, read("(id 123)")), ~Num(123.0));
		// should fail: assert_eq!(eval(&mut symt, read("(1 2 3)")), ~List(~[Num(1.0), Num(2.0), Num(3.0)]));
	}
}<commit_msg>add print BIF<commit_after>extern mod std;
use std::hashmap::HashMap;
use sexpr;

// A very simple LISP-like language
// Globally scoped, no closures

/// Our value types
#[deriving(Clone)]
pub enum LispValue {
	List(~[LispValue]),
	Atom(~str),
	Str(~str),
	Num(float),
	Fn(~[~str], ~LispValue), // args, body
	// XXX: we need the symbol table to be a @-ptr
	// otherwise we can't mutate it. &-ptrs give lifetime
	// headaches, and ~-ptrs give move headaches.
	BIF(~str, ~[~str], extern fn(@mut HashMap<~str, ~LispValue>, ~[~LispValue])->~LispValue) // built-in function (args, closure)
}

// XXX: this is ugly but it won't automatically derive Eq because of the extern fn
impl Eq for LispValue {
	fn eq(&self, other: &LispValue) -> bool {
		match (self.clone(), other.clone()) {
			(BIF(ref x, _, _), BIF(ref y, _, _)) if *x == *y => true,
			(Str(ref x), Str(ref y)) if *x == *y => true,
			(Num(ref x), Num(ref y)) if *x == *y => true,
			(Atom(ref x), Atom(ref y)) if *x == *y => true,
			(List(ref x), List(ref y)) if *x == *y => true,
			(Fn(ref x, ref x2), Fn(ref y, ref y2)) if *x == *y && *x2 == *y2 => true,
			_ => false
		}
	}
}

fn from_sexpr(sexpr: &sexpr::Value) -> ~LispValue {
	match *sexpr {
		sexpr::List(ref v) => ~List(v.map(|x| *from_sexpr(x))),
		sexpr::Num(v) => ~Num(v),
		sexpr::Str(ref v) => ~Str(v.clone()),
		sexpr::Atom(ref v) => ~Atom(v.clone())
	}
}

/// The type of the global symbol table (string to a value mapping).
type SymbolTable = HashMap<~str, ~LispValue>;

/// Returns a value representing the empty list
#[inline]
pub fn nil() -> ~LispValue {
	~List(~[])
}

/// Creates a new symbol table and returns it
pub fn new_symt() -> SymbolTable {
	HashMap::new()
}

/// Binds a symbol in the symbol table. Replaces if it already exists.
pub fn bind(symt: @mut SymbolTable, name: ~str, value: ~LispValue) {
	symt.insert(name, value);
}

/// Look up a symbol in the symbol table. Fails if not found.
pub fn lookup(symt: @mut SymbolTable, name: ~str) -> ~LispValue {
	match symt.find(&name) {
		Some(v) => v.clone(),
		None => fail!("couldn't find symbol: %s", name)
	}
}

/// Identity function
fn id_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue { v[0] }

// Print function
fn print_(_symt: @mut SymbolTable, v: ~[~LispValue]) -> ~LispValue {
	match v[0] {
		~Str(s) => printfln!("%s", s),
		_ => fail!("print takes an str")
	}
	nil()
}

/// Initializes standard library functions
pub fn init_std(symt: @mut SymbolTable) {
	bind(symt, ~"id", ~BIF(~"id", ~[~"x"], id_));
	bind(symt, ~"print", ~BIF(~"print", ~[~"msg"], print_));
}

fn apply(symt: @mut SymbolTable, f: ~LispValue, args: ~[~LispValue]) -> ~LispValue {
	match *f {
		BIF(name, fnargs, bif) => {
			// apply built-in function
			if fnargs.len() != args.len() {
				fail!("function '%s' requires %u arguments, but it received %u arguments",
					name, fnargs.len(), args.len())
			}

			bif(symt, args)
		}

		_ => fail!("apply: need function")
	}
}

/// Evaluates an s-expression and returns a value.
pub fn eval(symt: @mut SymbolTable, input: sexpr::Value) -> ~LispValue {
	match input {
		sexpr::List(v) => {
			if(v.len() == 0) {
				fail!("eval given empty list")
			}

			// XXX: If we don't clone, the `match` partially moves v,
			// so we can't use it in the match arms.
			let v_ = v.clone();

			// evaluate a list as a function call
			match v[0] {
				sexpr::Atom(sym) => {
					let f = lookup(symt, sym);
					let args = v_.slice(1, v_.len());
					let xargs = args.map(|x| eval(symt, x.clone())); // eval'd args
					apply(symt, f, xargs)
				}
				_ => fail!("function calls take an atom"),
			}

		}
		_ => from_sexpr(&input) // return non-list values as they are
	}
}

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

	fn read(input: &str) -> sexpr::Value {
		from_str(input).unwrap()
	}

	#[test]
	fn test_eval() {
		let symt = @mut new_symt();
		init_std(symt);
		assert_eq!(eval(symt, read("123")), ~Num(123.0));
		assert_eq!(eval(symt, read("(id 123)")), ~Num(123.0));
		// should fail: assert_eq!(eval(&mut symt, read("(1 2 3)")), ~List(~[Num(1.0), Num(2.0), Num(3.0)]));
	}
}<|endoftext|>


<commit_before>use crate::local_network::INVALID_ADDRESS;
use crate::{checks, LocalNetwork, E};
use clap::ArgMatches;
use eth1::http::Eth1Id;
use eth1::{DEFAULT_CHAIN_ID, DEFAULT_NETWORK_ID};
use eth1_test_rig::GanacheEth1Instance;
use futures::prelude::*;
use node_test_rig::{
    environment::EnvironmentBuilder, testing_client_config, testing_validator_config,
    ClientGenesis, ValidatorFiles,
};
use rayon::prelude::*;
use sensitive_url::SensitiveUrl;
use std::cmp::max;
use std::net::{IpAddr, Ipv4Addr};
use std::time::Duration;
use tokio::time::sleep;
use types::{Epoch, EthSpec, MinimalEthSpec};

const FORK_EPOCH: u64 = 2;
const END_EPOCH: u64 = 16;

pub fn run_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
    let node_count = value_t!(matches, "nodes", usize).expect("missing nodes default");
    let validators_per_node = value_t!(matches, "validators_per_node", usize)
        .expect("missing validators_per_node default");
    let speed_up_factor =
        value_t!(matches, "speed_up_factor", u64).expect("missing speed_up_factor default");
    let continue_after_checks = matches.is_present("continue_after_checks");

    println!("Beacon Chain Simulator:");
    println!(" nodes:{}", node_count);
    println!(" validators_per_node:{}", validators_per_node);
    println!(" continue_after_checks:{}", continue_after_checks);

    // Generate the directories and keystores required for the validator clients.
    let validator_files = (0..node_count)
        .into_par_iter()
        .map(|i| {
            println!(
                "Generating keystores for validator {} of {}",
                i + 1,
                node_count
            );

            let indices =
                (i * validators_per_node..(i + 1) * validators_per_node).collect::<Vec<_>>();
            ValidatorFiles::with_keystores(&indices).unwrap()
        })
        .collect::<Vec<_>>();

    let log_level = "debug";
    let log_format = None;

    let mut env = EnvironmentBuilder::minimal()
        .async_logger(log_level, log_format)?
        .multi_threaded_tokio_runtime()?
        .build()?;

    let eth1_block_time = Duration::from_millis(15_000 / speed_up_factor);

    let spec = &mut env.eth2_config.spec;

    let total_validator_count = validators_per_node * node_count;
    let altair_fork_version = spec.altair_fork_version;

    spec.seconds_per_slot /= speed_up_factor;
    spec.seconds_per_slot = max(1, spec.seconds_per_slot);
    spec.eth1_follow_distance = 16;
    spec.genesis_delay = eth1_block_time.as_secs() * spec.eth1_follow_distance * 2;
    spec.min_genesis_time = 0;
    spec.min_genesis_active_validator_count = total_validator_count as u64;
    spec.seconds_per_eth1_block = 1;
    spec.altair_fork_epoch = Some(Epoch::new(FORK_EPOCH));

    let slot_duration = Duration::from_secs(spec.seconds_per_slot);
    let initial_validator_count = spec.min_genesis_active_validator_count as usize;
    let deposit_amount = env.eth2_config.spec.max_effective_balance;

    let context = env.core_context();

    let main_future = async {
        /*
         * Deploy the deposit contract, spawn tasks to keep creating new blocks and deposit
         * validators.
         */
        let ganache_eth1_instance =
            GanacheEth1Instance::new(DEFAULT_NETWORK_ID.into(), DEFAULT_CHAIN_ID.into()).await?;
        let deposit_contract = ganache_eth1_instance.deposit_contract;
        let network_id = ganache_eth1_instance.ganache.network_id();
        let chain_id = ganache_eth1_instance.ganache.chain_id();
        let ganache = ganache_eth1_instance.ganache;
        let eth1_endpoint = SensitiveUrl::parse(ganache.endpoint().as_str())
            .expect("Unable to parse ganache endpoint.");
        let deposit_contract_address = deposit_contract.address();

        // Start a timer that produces eth1 blocks on an interval.
        tokio::spawn(async move {
            let mut interval = tokio::time::interval(eth1_block_time);
            loop {
                interval.tick().await;
                let _ = ganache.evm_mine().await;
            }
        });

        // Submit deposits to the deposit contract.
        tokio::spawn(async move {
            for i in 0..total_validator_count {
                println!("Submitting deposit for validator {}...", i);
                let _ = deposit_contract
                    .deposit_deterministic_async::<E>(i, deposit_amount)
                    .await;
            }
        });

        let mut beacon_config = testing_client_config();

        beacon_config.genesis = ClientGenesis::DepositContract;
        beacon_config.eth1.endpoints = vec![eth1_endpoint];
        beacon_config.eth1.deposit_contract_address = deposit_contract_address;
        beacon_config.eth1.deposit_contract_deploy_block = 0;
        beacon_config.eth1.lowest_cached_block_number = 0;
        beacon_config.eth1.follow_distance = 1;
        beacon_config.eth1.node_far_behind_seconds = 20;
        beacon_config.dummy_eth1_backend = false;
        beacon_config.sync_eth1_chain = true;
        beacon_config.eth1.network_id = Eth1Id::from(network_id);
        beacon_config.eth1.chain_id = Eth1Id::from(chain_id);

        beacon_config.network.enr_address = Some(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));

        /*
         * Create a new `LocalNetwork` with one beacon node.
         */
        let network = LocalNetwork::new(context.clone(), beacon_config.clone()).await?;

        /*
         * One by one, add beacon nodes to the network.
         */
        for i in 0..node_count - 1 {
            let mut config = beacon_config.clone();
            if i % 2 == 0 {
                config.eth1.endpoints.insert(
                    0,
                    SensitiveUrl::parse(INVALID_ADDRESS).expect("Unable to parse invalid address"),
                );
            }
            network.add_beacon_node(config).await?;
        }

        /*
         * One by one, add validators to the network.
         */

        let executor = context.executor.clone();
        for (i, files) in validator_files.into_iter().enumerate() {
            let network_1 = network.clone();
            executor.spawn(
                async move {
                    println!("Adding validator client {}", i);
                    network_1
                        .add_validator_client(testing_validator_config(), i, files, i % 2 == 0)
                        .await
                        .expect("should add validator");
                },
                "vc",
            );
        }

        let duration_to_genesis = network.duration_to_genesis().await;
        println!("Duration to genesis: {}", duration_to_genesis.as_secs());
        sleep(duration_to_genesis).await;

        /*
         * Start the checks that ensure the network performs as expected.
         *
         * We start these checks immediately after the validators have started. This means we're
         * relying on the validator futures to all return immediately after genesis so that these
         * tests start at the right time. Whilst this is works well for now, it's subject to
         * breakage by changes to the VC.
         */
        let (finalization, block_prod, validator_count, onboarding, fork, sync_aggregate) = futures::join!(
            // Check that the chain finalizes at the first given opportunity.
            checks::verify_first_finalization(network.clone(), slot_duration),
            // Check that a block is produced at every slot.
            checks::verify_full_block_production_up_to(
                network.clone(),
                Epoch::new(END_EPOCH).start_slot(MinimalEthSpec::slots_per_epoch()),
                slot_duration,
            ),
            // Check that the chain starts with the expected validator count.
            checks::verify_initial_validator_count(
                network.clone(),
                slot_duration,
                initial_validator_count,
            ),
            // Check that validators greater than `spec.min_genesis_active_validator_count` are
            // onboarded at the first possible opportunity.
            checks::verify_validator_onboarding(
                network.clone(),
                slot_duration,
                total_validator_count,
            ),
            // Check that all nodes have transitioned to the new fork.
            checks::verify_fork_version(
                network.clone(),
                Epoch::new(FORK_EPOCH),
                slot_duration,
                altair_fork_version
            ),
            // Check that all sync aggregates are full.
            checks::verify_full_sync_aggregates_up_to(
                network.clone(),
                // Start checking for sync_aggregates at `FORK_EPOCH + 1` to account for
                // inefficiencies in finding subnet peers at the `fork_slot`.
                Epoch::new(FORK_EPOCH + 1).start_slot(MinimalEthSpec::slots_per_epoch()),
                Epoch::new(END_EPOCH).start_slot(MinimalEthSpec::slots_per_epoch()),
                slot_duration,
            )
        );

        block_prod?;
        finalization?;
        validator_count?;
        onboarding?;
        fork?;
        sync_aggregate?;

        // The `final_future` either completes immediately or never completes, depending on the value
        // of `continue_after_checks`.

        if continue_after_checks {
            future::pending::<()>().await;
        }
        /*
         * End the simulation by dropping the network. This will kill all running beacon nodes and
         * validator clients.
         */
        println!(
            "Simulation complete. Finished with {} beacon nodes and {} validator clients",
            network.beacon_node_count(),
            network.validator_client_count()
        );

        // Be explicit about dropping the network, as this kills all the nodes. This ensures
        // all the checks have adequate time to pass.
        drop(network);
        Ok::<(), String>(())
    };

    env.runtime().block_on(main_future).unwrap();

    env.fire_signal();
    env.shutdown_on_idle();

    Ok(())
}
<commit_msg>Fix simulator issues (#2802)<commit_after>use crate::local_network::INVALID_ADDRESS;
use crate::{checks, LocalNetwork, E};
use clap::ArgMatches;
use eth1::http::Eth1Id;
use eth1::{DEFAULT_CHAIN_ID, DEFAULT_NETWORK_ID};
use eth1_test_rig::GanacheEth1Instance;
use futures::prelude::*;
use node_test_rig::{
    environment::EnvironmentBuilder, testing_client_config, testing_validator_config,
    ClientGenesis, ValidatorFiles,
};
use rayon::prelude::*;
use sensitive_url::SensitiveUrl;
use std::cmp::max;
use std::net::{IpAddr, Ipv4Addr};
use std::time::Duration;
use tokio::time::sleep;
use types::{Epoch, EthSpec, MinimalEthSpec};

const FORK_EPOCH: u64 = 2;
const END_EPOCH: u64 = 16;

pub fn run_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
    let node_count = value_t!(matches, "nodes", usize).expect("missing nodes default");
    let validators_per_node = value_t!(matches, "validators_per_node", usize)
        .expect("missing validators_per_node default");
    let speed_up_factor =
        value_t!(matches, "speed_up_factor", u64).expect("missing speed_up_factor default");
    let continue_after_checks = matches.is_present("continue_after_checks");

    println!("Beacon Chain Simulator:");
    println!(" nodes:{}", node_count);
    println!(" validators_per_node:{}", validators_per_node);
    println!(" continue_after_checks:{}", continue_after_checks);

    // Generate the directories and keystores required for the validator clients.
    let validator_files = (0..node_count)
        .into_par_iter()
        .map(|i| {
            println!(
                "Generating keystores for validator {} of {}",
                i + 1,
                node_count
            );

            let indices =
                (i * validators_per_node..(i + 1) * validators_per_node).collect::<Vec<_>>();
            ValidatorFiles::with_keystores(&indices).unwrap()
        })
        .collect::<Vec<_>>();

    let log_level = "debug";
    let log_format = None;

    let mut env = EnvironmentBuilder::minimal()
        .async_logger(log_level, log_format)?
        .multi_threaded_tokio_runtime()?
        .build()?;

    let eth1_block_time = Duration::from_millis(15_000 / speed_up_factor);

    let spec = &mut env.eth2_config.spec;

    let total_validator_count = validators_per_node * node_count;
    let altair_fork_version = spec.altair_fork_version;

    spec.seconds_per_slot /= speed_up_factor;
    spec.seconds_per_slot = max(1, spec.seconds_per_slot);
    spec.eth1_follow_distance = 16;
    spec.genesis_delay = eth1_block_time.as_secs() * spec.eth1_follow_distance * 2;
    spec.min_genesis_time = 0;
    spec.min_genesis_active_validator_count = total_validator_count as u64;
    spec.seconds_per_eth1_block = eth1_block_time.as_secs();
    spec.altair_fork_epoch = Some(Epoch::new(FORK_EPOCH));

    let slot_duration = Duration::from_secs(spec.seconds_per_slot);
    let initial_validator_count = spec.min_genesis_active_validator_count as usize;
    let deposit_amount = env.eth2_config.spec.max_effective_balance;

    let context = env.core_context();

    let main_future = async {
        /*
         * Deploy the deposit contract, spawn tasks to keep creating new blocks and deposit
         * validators.
         */
        let ganache_eth1_instance =
            GanacheEth1Instance::new(DEFAULT_NETWORK_ID.into(), DEFAULT_CHAIN_ID.into()).await?;
        let deposit_contract = ganache_eth1_instance.deposit_contract;
        let network_id = ganache_eth1_instance.ganache.network_id();
        let chain_id = ganache_eth1_instance.ganache.chain_id();
        let ganache = ganache_eth1_instance.ganache;
        let eth1_endpoint = SensitiveUrl::parse(ganache.endpoint().as_str())
            .expect("Unable to parse ganache endpoint.");
        let deposit_contract_address = deposit_contract.address();

        // Start a timer that produces eth1 blocks on an interval.
        tokio::spawn(async move {
            let mut interval = tokio::time::interval(eth1_block_time);
            loop {
                interval.tick().await;
                let _ = ganache.evm_mine().await;
            }
        });

        // Submit deposits to the deposit contract.
        tokio::spawn(async move {
            for i in 0..total_validator_count {
                println!("Submitting deposit for validator {}...", i);
                let _ = deposit_contract
                    .deposit_deterministic_async::<E>(i, deposit_amount)
                    .await;
            }
        });

        let mut beacon_config = testing_client_config();

        beacon_config.genesis = ClientGenesis::DepositContract;
        beacon_config.eth1.endpoints = vec![eth1_endpoint];
        beacon_config.eth1.deposit_contract_address = deposit_contract_address;
        beacon_config.eth1.deposit_contract_deploy_block = 0;
        beacon_config.eth1.lowest_cached_block_number = 0;
        beacon_config.eth1.follow_distance = 1;
        beacon_config.eth1.node_far_behind_seconds = 20;
        beacon_config.dummy_eth1_backend = false;
        beacon_config.sync_eth1_chain = true;
        beacon_config.eth1.auto_update_interval_millis = eth1_block_time.as_millis() as u64;
        beacon_config.eth1.network_id = Eth1Id::from(network_id);
        beacon_config.eth1.chain_id = Eth1Id::from(chain_id);
        beacon_config.network.target_peers = node_count - 1;

        beacon_config.network.enr_address = Some(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));

        /*
         * Create a new `LocalNetwork` with one beacon node.
         */
        let network = LocalNetwork::new(context.clone(), beacon_config.clone()).await?;

        /*
         * One by one, add beacon nodes to the network.
         */
        for i in 0..node_count - 1 {
            let mut config = beacon_config.clone();
            if i % 2 == 0 {
                config.eth1.endpoints.insert(
                    0,
                    SensitiveUrl::parse(INVALID_ADDRESS).expect("Unable to parse invalid address"),
                );
            }
            network.add_beacon_node(config).await?;
        }

        /*
         * One by one, add validators to the network.
         */

        let executor = context.executor.clone();
        for (i, files) in validator_files.into_iter().enumerate() {
            let network_1 = network.clone();
            executor.spawn(
                async move {
                    println!("Adding validator client {}", i);
                    network_1
                        .add_validator_client(testing_validator_config(), i, files, i % 2 == 0)
                        .await
                        .expect("should add validator");
                },
                "vc",
            );
        }

        let duration_to_genesis = network.duration_to_genesis().await;
        println!("Duration to genesis: {}", duration_to_genesis.as_secs());
        sleep(duration_to_genesis).await;

        /*
         * Start the checks that ensure the network performs as expected.
         *
         * We start these checks immediately after the validators have started. This means we're
         * relying on the validator futures to all return immediately after genesis so that these
         * tests start at the right time. Whilst this is works well for now, it's subject to
         * breakage by changes to the VC.
         */
        let (finalization, block_prod, validator_count, onboarding, fork, sync_aggregate) = futures::join!(
            // Check that the chain finalizes at the first given opportunity.
            checks::verify_first_finalization(network.clone(), slot_duration),
            // Check that a block is produced at every slot.
            checks::verify_full_block_production_up_to(
                network.clone(),
                Epoch::new(END_EPOCH).start_slot(MinimalEthSpec::slots_per_epoch()),
                slot_duration,
            ),
            // Check that the chain starts with the expected validator count.
            checks::verify_initial_validator_count(
                network.clone(),
                slot_duration,
                initial_validator_count,
            ),
            // Check that validators greater than `spec.min_genesis_active_validator_count` are
            // onboarded at the first possible opportunity.
            checks::verify_validator_onboarding(
                network.clone(),
                slot_duration,
                total_validator_count,
            ),
            // Check that all nodes have transitioned to the new fork.
            checks::verify_fork_version(
                network.clone(),
                Epoch::new(FORK_EPOCH),
                slot_duration,
                altair_fork_version
            ),
            // Check that all sync aggregates are full.
            checks::verify_full_sync_aggregates_up_to(
                network.clone(),
                // Start checking for sync_aggregates at `FORK_EPOCH + 1` to account for
                // inefficiencies in finding subnet peers at the `fork_slot`.
                Epoch::new(FORK_EPOCH + 1).start_slot(MinimalEthSpec::slots_per_epoch()),
                Epoch::new(END_EPOCH).start_slot(MinimalEthSpec::slots_per_epoch()),
                slot_duration,
            )
        );

        block_prod?;
        finalization?;
        validator_count?;
        onboarding?;
        fork?;
        sync_aggregate?;

        // The `final_future` either completes immediately or never completes, depending on the value
        // of `continue_after_checks`.

        if continue_after_checks {
            future::pending::<()>().await;
        }
        /*
         * End the simulation by dropping the network. This will kill all running beacon nodes and
         * validator clients.
         */
        println!(
            "Simulation complete. Finished with {} beacon nodes and {} validator clients",
            network.beacon_node_count(),
            network.validator_client_count()
        );

        // Be explicit about dropping the network, as this kills all the nodes. This ensures
        // all the checks have adequate time to pass.
        drop(network);
        Ok::<(), String>(())
    };

    env.runtime().block_on(main_future).unwrap();

    env.fire_signal();
    env.shutdown_on_idle();

    Ok(())
}
<|endoftext|>