<commit_before>extern crate crossbeam;
extern crate rand;

use std::sync::atomic::{AtomicUsize, Ordering};

use crossbeam::queue::ArrayQueue;
use rand::{thread_rng, Rng};

#[test]
fn smoke() {
    let q = ArrayQueue::new(1);

    q.push(7).unwrap();
    assert_eq!(q.pop(), Ok(7));

    q.push(8).unwrap();
    assert_eq!(q.pop(), Ok(8));
    assert!(q.pop().is_err());
}

#[test]
fn capacity() {
    for i in 1..10 {
        let q = ArrayQueue::<i32>::new(i);
        assert_eq!(q.capacity(), i);
    }
}

#[test]
fn len_empty_full() {
    let q = ArrayQueue::new(2);

    assert_eq!(q.len(), 0);
    assert_eq!(q.is_empty(), true);
    assert_eq!(q.is_full(), false);

    q.push(()).unwrap();

    assert_eq!(q.len(), 1);
    assert_eq!(q.is_empty(), false);
    assert_eq!(q.is_full(), false);

    q.push(()).unwrap();

    assert_eq!(q.len(), 2);
    assert_eq!(q.is_empty(), false);
    assert_eq!(q.is_full(), true);

    q.pop().unwrap();

    assert_eq!(q.len(), 1);
    assert_eq!(q.is_empty(), false);
    assert_eq!(q.is_full(), false);
}

#[test]
fn len() {
    const COUNT: usize = 25_000;
    const CAP: usize = 1000;

    let q = ArrayQueue::new(CAP);
    assert_eq!(q.len(), 0);

    for _ in 0..CAP / 10 {
        for i in 0..50 {
            q.push(i).unwrap();
            assert_eq!(q.len(), i + 1);
        }

        for i in 0..50 {
            q.pop().unwrap();
            assert_eq!(q.len(), 50 - i - 1);
        }
    }
    assert_eq!(q.len(), 0);

    for i in 0..CAP {
        q.push(i).unwrap();
        assert_eq!(q.len(), i + 1);
    }

    for _ in 0..CAP {
        q.pop().unwrap();
    }
    assert_eq!(q.len(), 0);

    crossbeam::scope(|scope| {
        scope.spawn(|| {
            for i in 0..COUNT {
                loop {
                    if let Ok(x) = q.pop() {
                        assert_eq!(x, i);
                        break;
                    }
                }
                let len = q.len();
                assert!(len <= CAP);
            }
        });

        scope.spawn(|| {
            for i in 0..COUNT {
                while q.push(i).is_err() {}
                let len = q.len();
                assert!(len <= CAP);
            }
        });
    });
    assert_eq!(q.len(), 0);
}

#[test]
fn spsc() {
    const COUNT: usize = 100_000;

    let q = ArrayQueue::new(3);

    crossbeam::scope(|scope| {
        scope.spawn(|| {
            for i in 0..COUNT {
                loop {
                    if let Ok(x) = q.pop() {
                        assert_eq!(x, i);
                        break;
                    }
                }
            }
            assert!(q.pop().is_err());
        });

        scope.spawn(|| {
            for i in 0..COUNT {
                while q.push(i).is_err() {}
            }
        });
    });
}

#[test]
fn mpmc() {
    const COUNT: usize = 25_000;
    const THREADS: usize = 4;

    let q = ArrayQueue::<usize>::new(3);
    let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::<Vec<_>>();

    crossbeam::scope(|scope| {
        for _ in 0..THREADS {
            scope.spawn(|| {
                for _ in 0..COUNT {
                    let n = loop {
                        if let Ok(x) = q.pop() {
                            break x;
                        }
                    };
                    v[n].fetch_add(1, Ordering::SeqCst);
                }
            });
        }
        for _ in 0..THREADS {
            scope.spawn(|| {
                for i in 0..COUNT {
                    while q.push(i).is_err() {}
                }
            });
        }
    });

    for c in v {
        assert_eq!(c.load(Ordering::SeqCst), THREADS);
    }
}

#[test]
fn drops() {
    const RUNS: usize = 100;

    static DROPS: AtomicUsize = AtomicUsize::new(0);

    #[derive(Debug, PartialEq)]
    struct DropCounter;

    impl Drop for DropCounter {
        fn drop(&mut self) {
            DROPS.fetch_add(1, Ordering::SeqCst);
        }
    }

    let mut rng = thread_rng();

    for _ in 0..RUNS {
        let steps = rng.gen_range(0, 10_000);
        let additional = rng.gen_range(0, 50);

        DROPS.store(0, Ordering::SeqCst);
        let q = ArrayQueue::new(50);

        crossbeam::scope(|scope| {
            scope.spawn(|| {
                for _ in 0..steps {
                    while q.pop().is_err() {}
                }
            });

            scope.spawn(|| {
                for _ in 0..steps {
                    while q.push(DropCounter).is_err() {
                        DROPS.fetch_sub(1, Ordering::SeqCst);
                    }
                }
            });
        });

        for _ in 0..additional {
            q.push(DropCounter).unwrap();
        }

        assert_eq!(DROPS.load(Ordering::SeqCst), steps);
        drop(q);
        assert_eq!(DROPS.load(Ordering::SeqCst), steps + additional);
    }
}

#[test]
fn linearizable() {
    const COUNT: usize = 25_000;
    const THREADS: usize = 4;

    let q = ArrayQueue::new(THREADS);

    crossbeam::scope(|scope| {
        for _ in 0..THREADS {
            scope.spawn(|| {
                for _ in 0..COUNT {
                    while q.push(0).is_err() {}
                    q.pop().unwrap();
                }
            });
        }
    });
}
<commit_msg>Fix compilation erros in scope()<commit_after>extern crate crossbeam;
extern crate rand;

use std::sync::atomic::{AtomicUsize, Ordering};

use crossbeam::queue::ArrayQueue;
use crossbeam::scope;
use rand::{thread_rng, Rng};

#[test]
fn smoke() {
    let q = ArrayQueue::new(1);

    q.push(7).unwrap();
    assert_eq!(q.pop(), Ok(7));

    q.push(8).unwrap();
    assert_eq!(q.pop(), Ok(8));
    assert!(q.pop().is_err());
}

#[test]
fn capacity() {
    for i in 1..10 {
        let q = ArrayQueue::<i32>::new(i);
        assert_eq!(q.capacity(), i);
    }
}

#[test]
fn len_empty_full() {
    let q = ArrayQueue::new(2);

    assert_eq!(q.len(), 0);
    assert_eq!(q.is_empty(), true);
    assert_eq!(q.is_full(), false);

    q.push(()).unwrap();

    assert_eq!(q.len(), 1);
    assert_eq!(q.is_empty(), false);
    assert_eq!(q.is_full(), false);

    q.push(()).unwrap();

    assert_eq!(q.len(), 2);
    assert_eq!(q.is_empty(), false);
    assert_eq!(q.is_full(), true);

    q.pop().unwrap();

    assert_eq!(q.len(), 1);
    assert_eq!(q.is_empty(), false);
    assert_eq!(q.is_full(), false);
}

#[test]
fn len() {
    const COUNT: usize = 25_000;
    const CAP: usize = 1000;

    let q = ArrayQueue::new(CAP);
    assert_eq!(q.len(), 0);

    for _ in 0..CAP / 10 {
        for i in 0..50 {
            q.push(i).unwrap();
            assert_eq!(q.len(), i + 1);
        }

        for i in 0..50 {
            q.pop().unwrap();
            assert_eq!(q.len(), 50 - i - 1);
        }
    }
    assert_eq!(q.len(), 0);

    for i in 0..CAP {
        q.push(i).unwrap();
        assert_eq!(q.len(), i + 1);
    }

    for _ in 0..CAP {
        q.pop().unwrap();
    }
    assert_eq!(q.len(), 0);

    scope(|scope| {
        scope.spawn(|_| {
            for i in 0..COUNT {
                loop {
                    if let Ok(x) = q.pop() {
                        assert_eq!(x, i);
                        break;
                    }
                }
                let len = q.len();
                assert!(len <= CAP);
            }
        });

        scope.spawn(|_| {
            for i in 0..COUNT {
                while q.push(i).is_err() {}
                let len = q.len();
                assert!(len <= CAP);
            }
        });
    }).unwrap();
    assert_eq!(q.len(), 0);
}

#[test]
fn spsc() {
    const COUNT: usize = 100_000;

    let q = ArrayQueue::new(3);

    scope(|scope| {
        scope.spawn(|_| {
            for i in 0..COUNT {
                loop {
                    if let Ok(x) = q.pop() {
                        assert_eq!(x, i);
                        break;
                    }
                }
            }
            assert!(q.pop().is_err());
        });

        scope.spawn(|_| {
            for i in 0..COUNT {
                while q.push(i).is_err() {}
            }
        });
    }).unwrap();
}

#[test]
fn mpmc() {
    const COUNT: usize = 25_000;
    const THREADS: usize = 4;

    let q = ArrayQueue::<usize>::new(3);
    let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::<Vec<_>>();

    scope(|scope| {
        for _ in 0..THREADS {
            scope.spawn(|_| {
                for _ in 0..COUNT {
                    let n = loop {
                        if let Ok(x) = q.pop() {
                            break x;
                        }
                    };
                    v[n].fetch_add(1, Ordering::SeqCst);
                }
            });
        }
        for _ in 0..THREADS {
            scope.spawn(|_| {
                for i in 0..COUNT {
                    while q.push(i).is_err() {}
                }
            });
        }
    }).unwrap();

    for c in v {
        assert_eq!(c.load(Ordering::SeqCst), THREADS);
    }
}

#[test]
fn drops() {
    const RUNS: usize = 100;

    static DROPS: AtomicUsize = AtomicUsize::new(0);

    #[derive(Debug, PartialEq)]
    struct DropCounter;

    impl Drop for DropCounter {
        fn drop(&mut self) {
            DROPS.fetch_add(1, Ordering::SeqCst);
        }
    }

    let mut rng = thread_rng();

    for _ in 0..RUNS {
        let steps = rng.gen_range(0, 10_000);
        let additional = rng.gen_range(0, 50);

        DROPS.store(0, Ordering::SeqCst);
        let q = ArrayQueue::new(50);

        scope(|scope| {
            scope.spawn(|_| {
                for _ in 0..steps {
                    while q.pop().is_err() {}
                }
            });

            scope.spawn(|_| {
                for _ in 0..steps {
                    while q.push(DropCounter).is_err() {
                        DROPS.fetch_sub(1, Ordering::SeqCst);
                    }
                }
            });
        }).unwrap();

        for _ in 0..additional {
            q.push(DropCounter).unwrap();
        }

        assert_eq!(DROPS.load(Ordering::SeqCst), steps);
        drop(q);
        assert_eq!(DROPS.load(Ordering::SeqCst), steps + additional);
    }
}

#[test]
fn linearizable() {
    const COUNT: usize = 25_000;
    const THREADS: usize = 4;

    let q = ArrayQueue::new(THREADS);

    scope(|scope| {
        for _ in 0..THREADS {
            scope.spawn(|_| {
                for _ in 0..COUNT {
                    while q.push(0).is_err() {}
                    q.pop().unwrap();
                }
            });
        }
    }).unwrap();
}
<|endoftext|>


<commit_before>extern crate compiletest_rs as compiletest;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


<commit_before>use maplit::hashmap;
use std::iter::once;
use tuf::crypto::{HashAlgorithm, PrivateKey, SignatureScheme};
use tuf::interchange::Json;
use tuf::metadata::{
    Delegation, Delegations, MetadataDescription, MetadataPath, RootMetadataBuilder,
    SnapshotMetadataBuilder, TargetsMetadataBuilder, TimestampMetadataBuilder, VirtualTargetPath,
};
use tuf::Tuf;

const ED25519_1_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-1.pk8.der");
const ED25519_2_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-2.pk8.der");
const ED25519_3_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-3.pk8.der");
const ED25519_4_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-4.pk8.der");
const ED25519_5_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-5.pk8.der");
const ED25519_6_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-6.pk8.der");

#[test]
fn simple_delegation() {
    let root_key = PrivateKey::from_pkcs8(ED25519_1_PK8, SignatureScheme::Ed25519).unwrap();
    let snapshot_key = PrivateKey::from_pkcs8(ED25519_2_PK8, SignatureScheme::Ed25519).unwrap();
    let targets_key = PrivateKey::from_pkcs8(ED25519_3_PK8, SignatureScheme::Ed25519).unwrap();
    let timestamp_key = PrivateKey::from_pkcs8(ED25519_4_PK8, SignatureScheme::Ed25519).unwrap();
    let delegation_key = PrivateKey::from_pkcs8(ED25519_5_PK8, SignatureScheme::Ed25519).unwrap();

    //// build the root ////

    let root = RootMetadataBuilder::new()
        .root_key(root_key.public().clone())
        .snapshot_key(snapshot_key.public().clone())
        .targets_key(targets_key.public().clone())
        .timestamp_key(timestamp_key.public().clone())
        .signed::<Json>(&root_key)
        .unwrap();

    let mut tuf =
        Tuf::<Json>::from_root_with_trusted_keys(root, 1, once(root_key.public())).unwrap();

    //// build the snapshot and timestamp ////

    let snapshot = SnapshotMetadataBuilder::new()
        .insert_metadata_description(
            MetadataPath::new("targets").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .insert_metadata_description(
            MetadataPath::new("delegation").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .signed::<Json>(&snapshot_key)
        .unwrap();

    let timestamp = TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
        .unwrap()
        .signed::<Json>(&timestamp_key)
        .unwrap();

    tuf.update_timestamp(timestamp).unwrap();
    tuf.update_snapshot(snapshot).unwrap();

    //// build the targets ////
    let delegations = Delegations::new(
        hashmap! { delegation_key.public().key_id().clone() => delegation_key.public().clone() },
        vec![Delegation::new(
            MetadataPath::new("delegation").unwrap(),
            false,
            1,
            vec![delegation_key.key_id().clone()]
                .iter()
                .cloned()
                .collect(),
            vec![VirtualTargetPath::new("foo".into()).unwrap()]
                .iter()
                .cloned()
                .collect(),
        )
        .unwrap()],
    )
    .unwrap();
    let targets = TargetsMetadataBuilder::new()
        .delegations(delegations)
        .signed::<Json>(&targets_key)
        .unwrap();

    tuf.update_targets(targets).unwrap();

    //// build the delegation ////
    let target_file: &[u8] = b"bar";
    let delegation = TargetsMetadataBuilder::new()
        .insert_target_from_reader(
            VirtualTargetPath::new("foo".into()).unwrap(),
            target_file,
            &[HashAlgorithm::Sha256],
        )
        .unwrap()
        .signed::<Json>(&delegation_key)
        .unwrap();

    tuf.update_delegation(&MetadataPath::new("delegation").unwrap(), delegation)
        .unwrap();

    assert!(tuf
        .target_description(&VirtualTargetPath::new("foo".into()).unwrap())
        .is_ok());
}

#[test]
fn nested_delegation() {
    let root_key = PrivateKey::from_pkcs8(ED25519_1_PK8, SignatureScheme::Ed25519).unwrap();
    let snapshot_key = PrivateKey::from_pkcs8(ED25519_2_PK8, SignatureScheme::Ed25519).unwrap();
    let targets_key = PrivateKey::from_pkcs8(ED25519_3_PK8, SignatureScheme::Ed25519).unwrap();
    let timestamp_key = PrivateKey::from_pkcs8(ED25519_4_PK8, SignatureScheme::Ed25519).unwrap();
    let delegation_a_key = PrivateKey::from_pkcs8(ED25519_5_PK8, SignatureScheme::Ed25519).unwrap();
    let delegation_b_key = PrivateKey::from_pkcs8(ED25519_6_PK8, SignatureScheme::Ed25519).unwrap();

    //// build the root ////

    let root = RootMetadataBuilder::new()
        .root_key(root_key.public().clone())
        .snapshot_key(snapshot_key.public().clone())
        .targets_key(targets_key.public().clone())
        .timestamp_key(timestamp_key.public().clone())
        .signed::<Json>(&root_key)
        .unwrap();

    let mut tuf =
        Tuf::<Json>::from_root_with_trusted_keys(root, 1, once(root_key.public())).unwrap();

    //// build the snapshot and timestamp ////

    let snapshot = SnapshotMetadataBuilder::new()
        .insert_metadata_description(
            MetadataPath::new("targets").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .insert_metadata_description(
            MetadataPath::new("delegation-a").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .insert_metadata_description(
            MetadataPath::new("delegation-b").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .signed::<Json>(&snapshot_key)
        .unwrap();

    let timestamp = TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
        .unwrap()
        .signed::<Json>(&timestamp_key)
        .unwrap();

    tuf.update_timestamp(timestamp).unwrap();
    tuf.update_snapshot(snapshot).unwrap();

    //// build the targets ////

    let delegations = Delegations::new(
        hashmap! {
            delegation_a_key.public().key_id().clone() => delegation_a_key.public().clone(),
        },
        vec![Delegation::new(
            MetadataPath::new("delegation-a").unwrap(),
            false,
            1,
            vec![delegation_a_key.key_id().clone()]
                .iter()
                .cloned()
                .collect(),
            vec![VirtualTargetPath::new("foo".into()).unwrap()]
                .iter()
                .cloned()
                .collect(),
        )
        .unwrap()],
    )
    .unwrap();
    let targets = TargetsMetadataBuilder::new()
        .delegations(delegations)
        .signed::<Json>(&targets_key)
        .unwrap();

    tuf.update_targets(targets).unwrap();

    //// build delegation A ////

    let delegations = Delegations::new(
        hashmap! { delegation_b_key.public().key_id().clone() => delegation_b_key.public().clone() },
        vec![Delegation::new(
            MetadataPath::new("delegation-b").unwrap(),
            false,
            1,
            vec![delegation_b_key.key_id().clone()].iter().cloned().collect(),
            vec![VirtualTargetPath::new("foo".into()).unwrap()].iter().cloned().collect(),
        )
        .unwrap()],
    )
    .unwrap();

    let delegation = TargetsMetadataBuilder::new()
        .delegations(delegations)
        .signed::<Json>(&delegation_a_key)
        .unwrap();

    tuf.update_delegation(&MetadataPath::new("delegation-a").unwrap(), delegation)
        .unwrap();

    //// build delegation B ////

    let target_file: &[u8] = b"bar";

    let delegation = TargetsMetadataBuilder::new()
        .insert_target_from_reader(
            VirtualTargetPath::new("foo".into()).unwrap(),
            target_file,
            &[HashAlgorithm::Sha256],
        )
        .unwrap()
        .signed::<Json>(&delegation_b_key)
        .unwrap();

    tuf.update_delegation(&MetadataPath::new("delegation-b").unwrap(), delegation)
        .unwrap();

    assert!(tuf
        .target_description(&VirtualTargetPath::new("foo".into()).unwrap())
        .is_ok());
}
<commit_msg>Add invalid delegations tests<commit_after>use maplit::hashmap;
use matches::assert_matches;
use std::iter::once;
use tuf::crypto::{HashAlgorithm, PrivateKey, SignatureScheme};
use tuf::interchange::Json;
use tuf::metadata::{
    Delegation, Delegations, MetadataDescription, MetadataPath, Role, RootMetadataBuilder,
    SnapshotMetadataBuilder, TargetsMetadataBuilder, TimestampMetadataBuilder, VirtualTargetPath,
};
use tuf::Error;
use tuf::Tuf;

const ED25519_1_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-1.pk8.der");
const ED25519_2_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-2.pk8.der");
const ED25519_3_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-3.pk8.der");
const ED25519_4_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-4.pk8.der");
const ED25519_5_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-5.pk8.der");
const ED25519_6_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-6.pk8.der");

#[test]
fn simple_delegation() {
    let root_key = PrivateKey::from_pkcs8(ED25519_1_PK8, SignatureScheme::Ed25519).unwrap();
    let snapshot_key = PrivateKey::from_pkcs8(ED25519_2_PK8, SignatureScheme::Ed25519).unwrap();
    let targets_key = PrivateKey::from_pkcs8(ED25519_3_PK8, SignatureScheme::Ed25519).unwrap();
    let timestamp_key = PrivateKey::from_pkcs8(ED25519_4_PK8, SignatureScheme::Ed25519).unwrap();
    let delegation_key = PrivateKey::from_pkcs8(ED25519_5_PK8, SignatureScheme::Ed25519).unwrap();

    //// build the root ////

    let root = RootMetadataBuilder::new()
        .root_key(root_key.public().clone())
        .snapshot_key(snapshot_key.public().clone())
        .targets_key(targets_key.public().clone())
        .timestamp_key(timestamp_key.public().clone())
        .signed::<Json>(&root_key)
        .unwrap();

    let mut tuf =
        Tuf::<Json>::from_root_with_trusted_keys(root, 1, once(root_key.public())).unwrap();

    //// build the snapshot and timestamp ////

    let snapshot = SnapshotMetadataBuilder::new()
        .insert_metadata_description(
            MetadataPath::new("targets").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .insert_metadata_description(
            MetadataPath::new("delegation").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .signed::<Json>(&snapshot_key)
        .unwrap();

    let timestamp = TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
        .unwrap()
        .signed::<Json>(&timestamp_key)
        .unwrap();

    tuf.update_timestamp(timestamp).unwrap();
    tuf.update_snapshot(snapshot).unwrap();

    //// build the targets ////
    let delegations = Delegations::new(
        hashmap! { delegation_key.public().key_id().clone() => delegation_key.public().clone() },
        vec![Delegation::new(
            MetadataPath::new("delegation").unwrap(),
            false,
            1,
            vec![delegation_key.key_id().clone()]
                .iter()
                .cloned()
                .collect(),
            vec![VirtualTargetPath::new("foo".into()).unwrap()]
                .iter()
                .cloned()
                .collect(),
        )
        .unwrap()],
    )
    .unwrap();
    let targets = TargetsMetadataBuilder::new()
        .delegations(delegations)
        .signed::<Json>(&targets_key)
        .unwrap();

    tuf.update_targets(targets).unwrap();

    //// build the delegation ////
    let target_file: &[u8] = b"bar";
    let delegation = TargetsMetadataBuilder::new()
        .insert_target_from_reader(
            VirtualTargetPath::new("foo".into()).unwrap(),
            target_file,
            &[HashAlgorithm::Sha256],
        )
        .unwrap()
        .signed::<Json>(&delegation_key)
        .unwrap();

    tuf.update_delegation(
        &MetadataPath::from_role(&Role::Targets),
        &MetadataPath::new("delegation").unwrap(),
        delegation,
    )
    .unwrap();

    assert!(tuf
        .target_description(&VirtualTargetPath::new("foo".into()).unwrap())
        .is_ok());
}

#[test]
fn nested_delegation() {
    let root_key = PrivateKey::from_pkcs8(ED25519_1_PK8, SignatureScheme::Ed25519).unwrap();
    let snapshot_key = PrivateKey::from_pkcs8(ED25519_2_PK8, SignatureScheme::Ed25519).unwrap();
    let targets_key = PrivateKey::from_pkcs8(ED25519_3_PK8, SignatureScheme::Ed25519).unwrap();
    let timestamp_key = PrivateKey::from_pkcs8(ED25519_4_PK8, SignatureScheme::Ed25519).unwrap();
    let delegation_a_key = PrivateKey::from_pkcs8(ED25519_5_PK8, SignatureScheme::Ed25519).unwrap();
    let delegation_b_key = PrivateKey::from_pkcs8(ED25519_6_PK8, SignatureScheme::Ed25519).unwrap();

    //// build the root ////

    let root = RootMetadataBuilder::new()
        .root_key(root_key.public().clone())
        .snapshot_key(snapshot_key.public().clone())
        .targets_key(targets_key.public().clone())
        .timestamp_key(timestamp_key.public().clone())
        .signed::<Json>(&root_key)
        .unwrap();

    let mut tuf =
        Tuf::<Json>::from_root_with_trusted_keys(root, 1, once(root_key.public())).unwrap();

    //// build the snapshot and timestamp ////

    let snapshot = SnapshotMetadataBuilder::new()
        .insert_metadata_description(
            MetadataPath::new("targets").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .insert_metadata_description(
            MetadataPath::new("delegation-a").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .insert_metadata_description(
            MetadataPath::new("delegation-b").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .signed::<Json>(&snapshot_key)
        .unwrap();

    let timestamp = TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
        .unwrap()
        .signed::<Json>(&timestamp_key)
        .unwrap();

    tuf.update_timestamp(timestamp).unwrap();
    tuf.update_snapshot(snapshot).unwrap();

    //// build the targets ////

    let delegations = Delegations::new(
        hashmap! {
            delegation_a_key.public().key_id().clone() => delegation_a_key.public().clone(),
        },
        vec![Delegation::new(
            MetadataPath::new("delegation-a").unwrap(),
            false,
            1,
            vec![delegation_a_key.key_id().clone()]
                .iter()
                .cloned()
                .collect(),
            vec![VirtualTargetPath::new("foo".into()).unwrap()]
                .iter()
                .cloned()
                .collect(),
        )
        .unwrap()],
    )
    .unwrap();
    let targets = TargetsMetadataBuilder::new()
        .delegations(delegations)
        .signed::<Json>(&targets_key)
        .unwrap();

    tuf.update_targets(targets).unwrap();

    //// build delegation A ////

    let delegations = Delegations::new(
        hashmap! { delegation_b_key.public().key_id().clone() => delegation_b_key.public().clone() },
        vec![Delegation::new(
            MetadataPath::new("delegation-b").unwrap(),
            false,
            1,
            vec![delegation_b_key.key_id().clone()].iter().cloned().collect(),
            vec![VirtualTargetPath::new("foo".into()).unwrap()].iter().cloned().collect(),
        )
        .unwrap()],
    )
    .unwrap();

    let delegation = TargetsMetadataBuilder::new()
        .delegations(delegations)
        .signed::<Json>(&delegation_a_key)
        .unwrap();

    tuf.update_delegation(
        &MetadataPath::from_role(&Role::Targets),
        &MetadataPath::new("delegation-a").unwrap(),
        delegation,
    )
    .unwrap();

    //// build delegation B ////

    let target_file: &[u8] = b"bar";

    let delegation = TargetsMetadataBuilder::new()
        .insert_target_from_reader(
            VirtualTargetPath::new("foo".into()).unwrap(),
            target_file,
            &[HashAlgorithm::Sha256],
        )
        .unwrap()
        .signed::<Json>(&delegation_b_key)
        .unwrap();

    tuf.update_delegation(
        &MetadataPath::new("delegation-a").unwrap(),
        &MetadataPath::new("delegation-b").unwrap(),
        delegation,
    )
    .unwrap();

    assert!(tuf
        .target_description(&VirtualTargetPath::new("foo".into()).unwrap())
        .is_ok());
}

#[test]
fn rejects_bad_delegation_signatures() {
    let root_key = PrivateKey::from_pkcs8(ED25519_1_PK8, SignatureScheme::Ed25519).unwrap();
    let snapshot_key = PrivateKey::from_pkcs8(ED25519_2_PK8, SignatureScheme::Ed25519).unwrap();
    let targets_key = PrivateKey::from_pkcs8(ED25519_3_PK8, SignatureScheme::Ed25519).unwrap();
    let timestamp_key = PrivateKey::from_pkcs8(ED25519_4_PK8, SignatureScheme::Ed25519).unwrap();
    let delegation_key = PrivateKey::from_pkcs8(ED25519_5_PK8, SignatureScheme::Ed25519).unwrap();
    let bad_delegation_key =
        PrivateKey::from_pkcs8(ED25519_6_PK8, SignatureScheme::Ed25519).unwrap();

    //// build the root ////

    let root = RootMetadataBuilder::new()
        .root_key(root_key.public().clone())
        .snapshot_key(snapshot_key.public().clone())
        .targets_key(targets_key.public().clone())
        .timestamp_key(timestamp_key.public().clone())
        .signed::<Json>(&root_key)
        .unwrap();

    let mut tuf =
        Tuf::<Json>::from_root_with_trusted_keys(root, 1, once(root_key.public())).unwrap();

    //// build the snapshot and timestamp ////

    let snapshot = SnapshotMetadataBuilder::new()
        .insert_metadata_description(
            MetadataPath::new("targets").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .insert_metadata_description(
            MetadataPath::new("delegation").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .signed::<Json>(&snapshot_key)
        .unwrap();

    let timestamp = TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
        .unwrap()
        .signed::<Json>(&timestamp_key)
        .unwrap();

    tuf.update_timestamp(timestamp).unwrap();
    tuf.update_snapshot(snapshot).unwrap();

    //// build the targets ////
    let delegations = Delegations::new(
        hashmap! { delegation_key.public().key_id().clone() => delegation_key.public().clone() },
        vec![Delegation::new(
            MetadataPath::new("delegation").unwrap(),
            false,
            1,
            vec![delegation_key.key_id().clone()]
                .iter()
                .cloned()
                .collect(),
            vec![VirtualTargetPath::new("foo".into()).unwrap()]
                .iter()
                .cloned()
                .collect(),
        )
        .unwrap()],
    )
    .unwrap();
    let targets = TargetsMetadataBuilder::new()
        .delegations(delegations)
        .signed::<Json>(&targets_key)
        .unwrap();

    tuf.update_targets(targets).unwrap();

    //// build the delegation ////
    let target_file: &[u8] = b"bar";
    let delegation = TargetsMetadataBuilder::new()
        .insert_target_from_reader(
            VirtualTargetPath::new("foo".into()).unwrap(),
            target_file,
            &[HashAlgorithm::Sha256],
        )
        .unwrap()
        .signed::<Json>(&bad_delegation_key)
        .unwrap();

    assert_matches!(
        tuf.update_delegation(
            &MetadataPath::from_role(&Role::Targets),
            &MetadataPath::new("delegation").unwrap(),
            delegation
        ),
        Err(Error::VerificationFailure(_))
    );

    assert_eq!(
        tuf.target_description(&VirtualTargetPath::new("foo".into()).unwrap()),
        Err(Error::TargetUnavailable)
    );
}

#[test]
fn diamond_delegation() {
    let etc_key = PrivateKey::from_pkcs8(ED25519_1_PK8, SignatureScheme::Ed25519).unwrap();
    let targets_key = PrivateKey::from_pkcs8(ED25519_2_PK8, SignatureScheme::Ed25519).unwrap();
    let delegation_a_key = PrivateKey::from_pkcs8(ED25519_3_PK8, SignatureScheme::Ed25519).unwrap();
    let delegation_b_key = PrivateKey::from_pkcs8(ED25519_4_PK8, SignatureScheme::Ed25519).unwrap();
    let delegation_c_key = PrivateKey::from_pkcs8(ED25519_5_PK8, SignatureScheme::Ed25519).unwrap();

    // Given delegations a, b, and c, targets delegates "foo" to delegation-a and "bar" to
    // delegation-b.
    //
    //             targets
    //              /  \
    //   delegation-a  delegation-b
    //              \  /
    //          delegation-c
    //
    // if delegation-a delegates "foo" to delegation-c, and
    //    delegation-b delegates "bar" to delegation-c, but
    //    delegation-b's signature is invalid, then delegation-c
    // can contain target "bar" which is unaccessible and target "foo" which is.
    //
    // Verify tuf::Tuf handles this situation correctly.

    //// build the root ////

    let root = RootMetadataBuilder::new()
        .root_key(etc_key.public().clone())
        .snapshot_key(etc_key.public().clone())
        .targets_key(targets_key.public().clone())
        .timestamp_key(etc_key.public().clone())
        .signed::<Json>(&etc_key)
        .unwrap();

    let mut tuf =
        Tuf::<Json>::from_root_with_trusted_keys(root, 1, once(etc_key.public())).unwrap();

    //// build the snapshot and timestamp ////

    let snapshot = SnapshotMetadataBuilder::new()
        .insert_metadata_description(
            MetadataPath::new("targets").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .insert_metadata_description(
            MetadataPath::new("delegation-a").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .insert_metadata_description(
            MetadataPath::new("delegation-b").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .insert_metadata_description(
            MetadataPath::new("delegation-c").unwrap(),
            MetadataDescription::from_reader(&*vec![0u8], 1, &[HashAlgorithm::Sha256]).unwrap(),
        )
        .signed::<Json>(&etc_key)
        .unwrap();

    let timestamp = TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
        .unwrap()
        .signed::<Json>(&etc_key)
        .unwrap();

    tuf.update_timestamp(timestamp).unwrap();
    tuf.update_snapshot(snapshot).unwrap();

    //// build the targets ////

    let delegations = Delegations::new(
        hashmap! {
            delegation_a_key.public().key_id().clone() => delegation_a_key.public().clone(),
            delegation_b_key.public().key_id().clone() => delegation_b_key.public().clone(),
        },
        vec![
            Delegation::new(
                MetadataPath::new("delegation-a").unwrap(),
                false,
                1,
                vec![delegation_a_key.key_id().clone()]
                    .iter()
                    .cloned()
                    .collect(),
                vec![VirtualTargetPath::new("foo".into()).unwrap()]
                    .iter()
                    .cloned()
                    .collect(),
            )
            .unwrap(),
            Delegation::new(
                MetadataPath::new("delegation-b").unwrap(),
                false,
                1,
                vec![delegation_b_key.key_id().clone()]
                    .iter()
                    .cloned()
                    .collect(),
                vec![VirtualTargetPath::new("bar".into()).unwrap()]
                    .iter()
                    .cloned()
                    .collect(),
            )
            .unwrap(),
        ],
    )
    .unwrap();
    let targets = TargetsMetadataBuilder::new()
        .delegations(delegations)
        .signed::<Json>(&targets_key)
        .unwrap();

    tuf.update_targets(targets).unwrap();

    //// build delegation A ////

    let delegations = Delegations::new(
        hashmap! { delegation_c_key.public().key_id().clone() => delegation_c_key.public().clone() },
        vec![Delegation::new(
            MetadataPath::new("delegation-c").unwrap(),
            false,
            1,
            vec![delegation_c_key.key_id().clone()].iter().cloned().collect(),
            vec![VirtualTargetPath::new("foo".into()).unwrap()].iter().cloned().collect(),
        )
        .unwrap()],
    )
    .unwrap();

    let delegation = TargetsMetadataBuilder::new()
        .delegations(delegations)
        .signed::<Json>(&delegation_a_key)
        .unwrap();

    tuf.update_delegation(
        &MetadataPath::from_role(&Role::Targets),
        &MetadataPath::new("delegation-a").unwrap(),
        delegation,
    )
    .unwrap();

    //// build delegation B ////

    let delegations = Delegations::new(
        hashmap! { delegation_c_key.public().key_id().clone() => delegation_c_key.public().clone() },
        vec![Delegation::new(
            MetadataPath::new("delegation-c").unwrap(),
            false,
            1,
            // oops, wrong key.
            vec![delegation_b_key.key_id().clone()].iter().cloned().collect(),
            vec![VirtualTargetPath::new("bar".into()).unwrap()].iter().cloned().collect(),
        )
        .unwrap()],
    )
    .unwrap();

    let delegation = TargetsMetadataBuilder::new()
        .delegations(delegations)
        .signed::<Json>(&delegation_b_key)
        .unwrap();

    tuf.update_delegation(
        &MetadataPath::from_role(&Role::Targets),
        &MetadataPath::new("delegation-b").unwrap(),
        delegation,
    )
    .unwrap();

    //// build delegation C ////

    let foo_target_file: &[u8] = b"foo contents";
    let bar_target_file: &[u8] = b"bar contents";

    let delegation = TargetsMetadataBuilder::new()
        .insert_target_from_reader(
            VirtualTargetPath::new("foo".into()).unwrap(),
            foo_target_file,
            &[HashAlgorithm::Sha256],
        )
        .unwrap()
        .insert_target_from_reader(
            VirtualTargetPath::new("bar".into()).unwrap(),
            bar_target_file,
            &[HashAlgorithm::Sha256],
        )
        .unwrap()
        .signed::<Json>(&delegation_c_key)
        .unwrap();

    //// Verify delegation-c is valid, but only when updated through delegation-a.

    tuf.update_delegation(
        &MetadataPath::new("delegation-a").unwrap(),
        &MetadataPath::new("delegation-c").unwrap(),
        delegation.clone(),
    )
    .unwrap();

    assert_matches!(
        tuf.update_delegation(
            &MetadataPath::new("delegation-b").unwrap(),
            &MetadataPath::new("delegation-c").unwrap(),
            delegation
        ),
        Err(Error::VerificationFailure(_))
    );

    assert!(tuf
        .target_description(&VirtualTargetPath::new("foo".into()).unwrap())
        .is_ok());

    assert_matches!(
        tuf.target_description(&VirtualTargetPath::new("bar".into()).unwrap()),
        Err(Error::TargetUnavailable)
    );
}
<|endoftext|>


<commit_before>extern crate futures;

use futures::{Future, Stream};
use futures::Async::*;
use futures::future::{self, ReadyQueue};
use futures::sync::oneshot;

#[test]
fn basic_usage() {
    future::lazy(move || {
        let mut queue = ReadyQueue::new();
        let (tx1, rx1) = oneshot::channel();
        let (tx2, rx2) = oneshot::channel();
        let (tx3, rx3) = oneshot::channel();

        queue.push(rx1);
        queue.push(rx2);
        queue.push(rx3);

        assert!(!queue.poll().unwrap().is_ready());

        tx2.send("hello").unwrap();

        assert_eq!(Ready(Some("hello")), queue.poll().unwrap());
        assert!(!queue.poll().unwrap().is_ready());

        tx1.send("world").unwrap();
        tx3.send("world2").unwrap();

        assert_eq!(Ready(Some("world")), queue.poll().unwrap());
        assert_eq!(Ready(Some("world2")), queue.poll().unwrap());
        assert!(!queue.poll().unwrap().is_ready());

        Ok::<_, ()>(())
    }).wait().unwrap();
}

#[test]
fn resolving_errors() {
    future::lazy(move || {
        let mut queue = ReadyQueue::new();
        let (tx1, rx1) = oneshot::channel();
        let (tx2, rx2) = oneshot::channel();
        let (tx3, rx3) = oneshot::channel();

        queue.push(rx1);
        queue.push(rx2);
        queue.push(rx3);

        assert!(!queue.poll().unwrap().is_ready());

        drop(tx2);

        assert!(queue.poll().is_err());
        assert!(!queue.poll().unwrap().is_ready());

        drop(tx1);
        tx3.send("world2").unwrap();

        assert!(queue.poll().is_err());
        assert_eq!(Ready(Some("world2")), queue.poll().unwrap());
        assert!(!queue.poll().unwrap().is_ready());

        Ok::<_, ()>(())
    }).wait().unwrap();
}

#[test]
fn dropping_ready_queue() {
    future::lazy(move || {
        let mut queue = ReadyQueue::new();
        let (mut tx1, rx1) = oneshot::channel::<()>();
        let (mut tx2, rx2) = oneshot::channel::<()>();
        let (mut tx3, rx3) = oneshot::channel::<()>();

        queue.push(rx1);
        queue.push(rx2);
        queue.push(rx3);

        assert!(!tx1.poll_cancel().unwrap().is_ready());
        assert!(!tx2.poll_cancel().unwrap().is_ready());
        assert!(!tx3.poll_cancel().unwrap().is_ready());

        drop(queue);

        assert!(tx1.poll_cancel().unwrap().is_ready());
        assert!(tx2.poll_cancel().unwrap().is_ready());
        assert!(tx3.poll_cancel().unwrap().is_ready());

        Ok::<_, ()>(())
    }).wait().unwrap();
}

#[test]
fn stress() {
    const ITER: usize = 500;

    use std::sync::{Arc, Barrier};
    use std::thread;

    for i in 0..ITER {
        let n = (i % 10) + 1;

        let mut queue = ReadyQueue::new();
        let barrier = Arc::new(Barrier::new(n + 1));

        for num in 0..n {
            let barrier = barrier.clone();
            let (tx, rx) = oneshot::channel();

            queue.push(rx);

            thread::spawn(move || {
                barrier.wait();
                tx.send(num).unwrap();
            });
        }

        barrier.wait();

        let mut rx: Vec<_> = queue.wait()
            .take(n)
            .map(|res| res.unwrap())
            .collect();

        assert_eq!(rx.len(), n);

        rx.sort();

        for num in 0..n {
            assert_eq!(rx[num], num);
        }
    }
}
<commit_msg>Improve the test slightly<commit_after>extern crate futures;

use futures::{Future, Stream};
use futures::Async::*;
use futures::future::{self, ReadyQueue};
use futures::sync::oneshot;

#[test]
fn basic_usage() {
    future::lazy(move || {
        let mut queue = ReadyQueue::new();
        let (tx1, rx1) = oneshot::channel();
        let (tx2, rx2) = oneshot::channel();
        let (tx3, rx3) = oneshot::channel();

        queue.push(rx1);
        queue.push(rx2);
        queue.push(rx3);

        assert!(!queue.poll().unwrap().is_ready());

        tx2.send("hello").unwrap();

        assert_eq!(Ready(Some("hello")), queue.poll().unwrap());
        assert!(!queue.poll().unwrap().is_ready());

        tx1.send("world").unwrap();
        tx3.send("world2").unwrap();

        assert_eq!(Ready(Some("world")), queue.poll().unwrap());
        assert_eq!(Ready(Some("world2")), queue.poll().unwrap());
        assert!(!queue.poll().unwrap().is_ready());

        Ok::<_, ()>(())
    }).wait().unwrap();
}

#[test]
fn resolving_errors() {
    future::lazy(move || {
        let mut queue = ReadyQueue::new();
        let (tx1, rx1) = oneshot::channel();
        let (tx2, rx2) = oneshot::channel();
        let (tx3, rx3) = oneshot::channel();

        queue.push(rx1);
        queue.push(rx2);
        queue.push(rx3);

        assert!(!queue.poll().unwrap().is_ready());

        drop(tx2);

        assert!(queue.poll().is_err());
        assert!(!queue.poll().unwrap().is_ready());

        drop(tx1);
        tx3.send("world2").unwrap();

        assert!(queue.poll().is_err());
        assert_eq!(Ready(Some("world2")), queue.poll().unwrap());
        assert!(!queue.poll().unwrap().is_ready());

        Ok::<_, ()>(())
    }).wait().unwrap();
}

#[test]
fn dropping_ready_queue() {
    future::lazy(move || {
        let mut queue = ReadyQueue::new();
        let (mut tx1, rx1) = oneshot::channel::<()>();
        let (mut tx2, rx2) = oneshot::channel::<()>();
        let (mut tx3, rx3) = oneshot::channel::<()>();

        queue.push(rx1);
        queue.push(rx2);
        queue.push(rx3);

        assert!(!tx1.poll_cancel().unwrap().is_ready());
        assert!(!tx2.poll_cancel().unwrap().is_ready());
        assert!(!tx3.poll_cancel().unwrap().is_ready());

        drop(queue);

        assert!(tx1.poll_cancel().unwrap().is_ready());
        assert!(tx2.poll_cancel().unwrap().is_ready());
        assert!(tx3.poll_cancel().unwrap().is_ready());

        Ok::<_, ()>(())
    }).wait().unwrap();
}

#[test]
fn stress() {
    const ITER: usize = 300;

    use std::sync::{Arc, Barrier};
    use std::thread;

    for i in 0..ITER {
        let n = (i % 10) + 1;

        let mut queue = ReadyQueue::new();

        for _ in 0..5 {
            let barrier = Arc::new(Barrier::new(n + 1));

            for num in 0..n {
                let barrier = barrier.clone();
                let (tx, rx) = oneshot::channel();

                queue.push(rx);

                thread::spawn(move || {
                    barrier.wait();
                    tx.send(num).unwrap();
                });
            }

            barrier.wait();

            let mut sync = queue.wait();

            let mut rx: Vec<_> = (&mut sync)
                .take(n)
                .map(|res| res.unwrap())
                .collect();

            assert_eq!(rx.len(), n);

            rx.sort();

            for num in 0..n {
                assert_eq!(rx[num], num);
            }

            queue = sync.into_inner();
        }
    }
}
<|endoftext|>


<commit_before>#[test]
fn with_anon_struct() {
    mod ffi { bindgen!("headers/struct_with_anon_struct.h"); }
    let mut x = ffi::Struct_foo { bar: ffi::Struct_Unnamed1 { a: 0, b: 0 } };

    x.bar.a = 1;
    x.bar.b = 2;

    assert_eq!(x.bar.a, 1);
    assert_eq!(x.bar.b, 2);
}

#[test]
fn with_anon_struct_array() {
    mod ffi { bindgen!("headers/struct_with_anon_struct_array.h"); }
    let mut x = ffi::Struct_foo { bar: [
        ffi::Struct_Unnamed1 { a: 0, b: 0 },
        ffi::Struct_Unnamed1 { a: 1, b: 1 } ]
    };

    x.bar[1].a = 1;
    x.bar[1].b = 2;

    assert_eq!(x.bar[1].a, 1);
    assert_eq!(x.bar[1].b, 2);
}

#[test]
fn with_anon_struct_pointer() {
    mod ffi { bindgen!("headers/struct_with_anon_struct_pointer.h"); }
    let mut unnamed = box ffi::Struct_Unnamed1 { a: 0, b: 0 };

    unsafe {
        let mut x = ffi::Struct_foo { bar: ::std::mem::transmute(unnamed) };

        (*x.bar).a = 1;
        (*x.bar).b = 2;

        assert_eq!((*x.bar).a, 1);
        assert_eq!((*x.bar).b, 2);

        ::std::ptr::read(x.bar);
    }
}

#[test]
fn with_anon_union() {
    mod ffi { bindgen!("headers/struct_with_anon_union.h"); }
    let mut x = ffi::Struct_foo { bar: ffi::Union_Unnamed1 { _bindgen_data_: [0] } };

    unsafe {
        *x.bar.a() = 0x12345678;
        assert_eq!(*x.bar.a(), 0x12345678);
        assert_eq!(*x.bar.b(), 0x5678);
    }
}

#[test]
fn with_anon_unnamed_struct() {
    mod ffi { bindgen!("headers/struct_with_anon_unnamed_struct.h"); }
    let mut x = ffi::Struct_foo { _bindgen_data_1_: [0, 0] };

    unsafe {
        *x.a() = 0x12345678;
        *x.b() = 0x87654321;
        assert_eq!(*x.a(), 0x12345678);
        assert_eq!(*x.b(), 0x87654321);
    }
}

#[test]
fn with_anon_unnamed_union() {
    mod ffi { bindgen!("headers/struct_with_anon_unnamed_union.h"); }
    let mut x = ffi::Struct_foo { _bindgen_data_1_: [0] };

    unsafe {
        *x.a() = 0x12345678;
        assert_eq!(*x.a(), 0x12345678);
        assert_eq!(*x.b(), 0x5678);
    }
}

#[test]
fn with_nesting() {
    mod ffi { bindgen!("headers/struct_with_nesting.h"); }
    let mut x = ffi::Struct_foo { a: 0, _bindgen_data_1_: [0] };

    unsafe {
        x.a = 0x12345678;
        *x.b() = 0x87654321;

        assert_eq!(x.a, 0x12345678);
        assert_eq!(*x.b(), 0x87654321);
        assert_eq!(*x.c1(), 0x4321);
        assert_eq!(*x.c2(), 0x8765);
        assert_eq!(*x.d1(), 0x21);
        assert_eq!(*x.d2(), 0x43);
        assert_eq!(*x.d3(), 0x65);
        assert_eq!(*x.d4(), 0x87);
    }
}

#[test]
fn with_contain_fwd_decl_struct() {
    assert_bind_eq!("headers/struct_containing_forward_declared_struct.h", cx,
        quote_item!(cx,
            #[repr(C)]
            #[deriving(Copy)]
            pub struct Struct_a {
                pub val_a: *mut Struct_b,
            }
        ),
        quote_item!(cx,
            #[repr(C)]
            #[deriving(Copy)]
            pub struct Struct_b;
        ));
}

#[test]
fn with_unnamed_bitfields() {
    assert_bind_eq!("headers/unnamed_bitfields.h", cx,
        quote_item!(cx,
            #[repr(C)]
            #[deriving(Copy)]
            pub struct Struct_bitfield {
                pub a: ::libc::c_ushort,
                pub b: ::libc::c_ushort,
                pub c: ::libc::c_ushort,
                pub unnamed_field1: ::libc::c_ushort,
                pub unnamed_field2: ::libc::c_ushort,
                pub d: ::libc::c_ushort,
            }
        ));
}

#[test]
fn with_fwd_decl_struct() {
    mod ffi { bindgen!("headers/forward_declared_struct.h"); }

    let a = ffi::Struct_a { b: 1 };
    let c = ffi::Struct_c { d: 1 };

    a.b;
    c.d;
}
<commit_msg>Fixes a struct test that was previously incorrect.<commit_after>#[test]
fn with_anon_struct() {
    mod ffi { bindgen!("headers/struct_with_anon_struct.h"); }
    let mut x = ffi::Struct_foo { bar: ffi::Struct_Unnamed1 { a: 0, b: 0 } };

    x.bar.a = 1;
    x.bar.b = 2;

    assert_eq!(x.bar.a, 1);
    assert_eq!(x.bar.b, 2);
}

#[test]
fn with_anon_struct_array() {
    mod ffi { bindgen!("headers/struct_with_anon_struct_array.h"); }
    let mut x = ffi::Struct_foo { bar: [
        ffi::Struct_Unnamed1 { a: 0, b: 0 },
        ffi::Struct_Unnamed1 { a: 1, b: 1 } ]
    };

    x.bar[1].a = 1;
    x.bar[1].b = 2;

    assert_eq!(x.bar[1].a, 1);
    assert_eq!(x.bar[1].b, 2);
}

#[test]
fn with_anon_struct_pointer() {
    mod ffi { bindgen!("headers/struct_with_anon_struct_pointer.h"); }
    let mut unnamed = box ffi::Struct_Unnamed1 { a: 0, b: 0 };

    unsafe {
        let mut x = ffi::Struct_foo { bar: ::std::mem::transmute(unnamed) };

        (*x.bar).a = 1;
        (*x.bar).b = 2;

        assert_eq!((*x.bar).a, 1);
        assert_eq!((*x.bar).b, 2);

        ::std::ptr::read(x.bar);
    }
}

#[test]
fn with_anon_union() {
    mod ffi { bindgen!("headers/struct_with_anon_union.h"); }
    let mut x = ffi::Struct_foo { bar: ffi::Union_Unnamed1 { _bindgen_data_: [0] } };

    unsafe {
        *x.bar.a() = 0x12345678;
        assert_eq!(*x.bar.a(), 0x12345678);
        assert_eq!(*x.bar.b(), 0x5678);
    }
}

#[test]
fn with_anon_unnamed_struct() {
    mod ffi { bindgen!("headers/struct_with_anon_unnamed_struct.h"); }
    let mut x = ffi::Struct_foo { _bindgen_data_1_: [0, 0] };

    unsafe {
        *x.a() = 0x12345678;
        *x.b() = 0x87654321;
        assert_eq!(*x.a(), 0x12345678);
        assert_eq!(*x.b(), 0x87654321);
    }
}

#[test]
fn with_anon_unnamed_union() {
    mod ffi { bindgen!("headers/struct_with_anon_unnamed_union.h"); }
    let mut x = ffi::Struct_foo { _bindgen_data_1_: [0] };

    unsafe {
        *x.a() = 0x12345678;
        assert_eq!(*x.a(), 0x12345678);
        assert_eq!(*x.b(), 0x5678);
    }
}

#[test]
fn with_nesting() {
    mod ffi { bindgen!("headers/struct_with_nesting.h"); }
    let mut x = ffi::Struct_foo { a: 0, _bindgen_data_1_: [0] };

    unsafe {
        x.a = 0x12345678;
        *x.b() = 0x87654321;

        assert_eq!(x.a, 0x12345678);
        assert_eq!(*x.b(), 0x87654321);
        assert_eq!(*x.c1(), 0x4321);
        assert_eq!(*x.c2(), 0x8765);
        assert_eq!(*x.d1(), 0x21);
        assert_eq!(*x.d2(), 0x43);
        assert_eq!(*x.d3(), 0x65);
        assert_eq!(*x.d4(), 0x87);
    }
}

#[test]
fn containing_fwd_decl_struct() {
    assert_bind_eq!("headers/struct_containing_forward_declared_struct.h", cx,
        quote_item!(cx,
            #[repr(C)]
            #[deriving(Copy)]
            pub struct Struct_a {
                pub val_a: *mut Struct_b,
            }
        ),
        quote_item!(cx,
            #[repr(C)]
            #[deriving(Copy)]
            pub struct Struct_b {
                pub val_b: ::libc::c_int,
            }
        ));
}

#[test]
fn with_unnamed_bitfields() {
    assert_bind_eq!("headers/unnamed_bitfields.h", cx,
        quote_item!(cx,
            #[repr(C)]
            #[deriving(Copy)]
            pub struct Struct_bitfield {
                pub a: ::libc::c_ushort,
                pub b: ::libc::c_ushort,
                pub c: ::libc::c_ushort,
                pub unnamed_field1: ::libc::c_ushort,
                pub unnamed_field2: ::libc::c_ushort,
                pub d: ::libc::c_ushort,
            }
        ));
}

#[test]
fn with_fwd_decl_struct() {
    mod ffi { bindgen!("headers/forward_declared_struct.h"); }

    let a = ffi::Struct_a { b: 1 };
    let c = ffi::Struct_c { d: 1 };

    a.b;
    c.d;
}
<|endoftext|>


<commit_before>use bs58;
use sodiumoxide::crypto::sign;
use sodiumoxide::randombytes;
use std::fmt;

use super::error::*;
use super::sigpair::*;
use super::util::*;

pub const PUB_ADDRESS_PREFIX: &str = "GOD";
const PRIV_BUF_PREFIX: u8 = 0x01;
const PUB_BUF_PREFIX: u8 = 0x02;

pub trait Wif<T, U> {
    fn from_wif(s: &str) -> Result<T, WifError>;
    fn to_wif(&self) -> U;
}

pub struct PrivateWif(Box<str>);

impl fmt::Display for PrivateWif {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", &*self.0)
    }
}

impl std::ops::Deref for PrivateWif {
    type Target = str;

    fn deref(&self) -> &str {
        &self.0
    }
}

impl std::ops::Drop for PrivateWif {
    fn drop(&mut self) {
        let bytes = unsafe { self.0.as_bytes_mut() };
        sodiumoxide::utils::memzero(bytes);
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct PublicKey(pub(crate) sign::PublicKey);

impl PublicKey {
    #[inline]
    pub fn verify(&self, msg: &[u8], sig: &sign::Signature) -> bool {
        sign::verify_detached(sig, msg, &self.0)
    }

    #[inline]
    pub fn from_slice(bytes: &[u8]) -> Option<PublicKey> {
        let key = sign::PublicKey::from_slice(bytes)?;
        Some(PublicKey(key))
    }
}

impl Wif<PublicKey, Box<str>> for PublicKey {
    fn from_wif(s: &str) -> Result<PublicKey, WifError> {
        if s.len() < 3 || &s[0..3] != PUB_ADDRESS_PREFIX {
            return Err(WifError::new(WifErrorKind::InvalidPrefix));
        }
        let raw = match bs58::decode(&s[3..]).into_vec() {
            Ok(bytes) => bytes,
            Err(_) => {
                return Err(WifError::new(WifErrorKind::InvalidBs58Encoding));
            }
        };
        if raw.len() != 37 {
            return Err(WifError::new(WifErrorKind::InvalidLen));
        } else if raw[0] != PUB_BUF_PREFIX {
            return Err(WifError::new(WifErrorKind::InvalidPrefix));
        }

        let prefixed_key = &raw[0..raw.len() - 4];
        {
            let checksum_a = &raw[raw.len() - 4..raw.len()];
            let checksum_b = &double_sha256(prefixed_key)[0..4];
            if checksum_a != checksum_b {
                return Err(WifError::new(WifErrorKind::InvalidChecksum));
            }
        }

        let key = &prefixed_key[1..prefixed_key.len()];
        Ok(PublicKey(sign::PublicKey::from_slice(key).unwrap()))
    }

    fn to_wif(&self) -> Box<str> {
        let mut buf: Vec<u8> = Vec::<u8>::with_capacity(37);
        buf.push(PUB_BUF_PREFIX);
        buf.extend_from_slice(self.0.as_ref());

        let checksum = &double_sha256(&buf)[0..4];
        buf.extend_from_slice(checksum);

        let mut s = bs58::encode(buf).into_string();
        s.insert_str(0, PUB_ADDRESS_PREFIX);
        s.into_boxed_str()
    }
}

impl AsRef<[u8]> for PublicKey {
    fn as_ref(&self) -> &[u8] {
        self.0.as_ref()
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct PrivateKey {
    seed: sign::Seed,
    key: sign::SecretKey,
}

impl PrivateKey {
    #[inline]
    pub fn sign(&self, msg: &[u8]) -> sign::Signature {
        sign::sign_detached(msg, &self.key)
    }

    #[inline]
    pub fn from_slice(seed: &[u8], key: &[u8]) -> Option<PrivateKey> {
        Some(PrivateKey {
            seed: sign::Seed::from_slice(seed)?,
            key: sign::SecretKey::from_slice(key)?,
        })
    }
}

impl Wif<KeyPair, PrivateWif> for PrivateKey {
    fn from_wif(s: &str) -> Result<KeyPair, WifError> {
        let raw = match bs58::decode(s).into_vec() {
            Ok(bytes) => bytes,
            Err(_) => {
                return Err(WifError::new(WifErrorKind::InvalidBs58Encoding));
            }
        };
        if raw.len() != 37 {
            return Err(WifError::new(WifErrorKind::InvalidLen));
        } else if raw[0] != PRIV_BUF_PREFIX {
            return Err(WifError::new(WifErrorKind::InvalidPrefix));
        }

        let key = &raw[0..raw.len() - 4];
        {
            let checksum_a = &raw[raw.len() - 4..raw.len()];
            let checksum_b = &double_sha256(key)[0..4];
            if checksum_a != checksum_b {
                return Err(WifError::new(WifErrorKind::InvalidChecksum));
            }
        }

        let seed = sign::Seed::from_slice(&key[1..]).unwrap();
        let (pk, sk) = sign::keypair_from_seed(&seed);
        Ok(KeyPair(PublicKey(pk), PrivateKey { seed, key: sk }))
    }

    fn to_wif(&self) -> PrivateWif {
        let mut buf = Vec::<u8>::with_capacity(37);
        buf.push(PRIV_BUF_PREFIX);
        buf.extend_from_slice(&self.seed.0);

        let checksum = &double_sha256(&buf)[0..4];
        buf.extend_from_slice(checksum);

        PrivateWif(bs58::encode(buf).into_string().into_boxed_str())
    }
}

#[derive(Debug, Clone)]
pub struct KeyPair(pub PublicKey, pub PrivateKey);

impl KeyPair {
    #[inline]
    pub fn sign(&self, msg: &[u8]) -> SigPair {
        SigPair {
            pub_key: self.0.clone(),
            signature: self.1.sign(msg),
        }
    }

    #[inline]
    pub fn verify(&self, msg: &[u8], sig: &sign::Signature) -> bool {
        PublicKey::verify(&self.0, msg, sig)
    }

    pub fn gen_keypair() -> KeyPair {
        let mut raw_seed: [u8; sign::SEEDBYTES] = [0; sign::SEEDBYTES];
        randombytes::randombytes_into(&mut raw_seed);
        let seed = sign::Seed::from_slice(&raw_seed).unwrap();
        let (pk, sk) = sign::keypair_from_seed(&seed);
        KeyPair(PublicKey(pk), PrivateKey { seed, key: sk })
    }
}

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

    #[test]
    fn test_create_and_recover_keys() {
        let kp = KeyPair::gen_keypair();

        let pk = &*kp.0.to_wif();
        assert_eq!(&*PublicKey::from_wif(pk).unwrap().to_wif(), pk);

        let sk = &*kp.1.to_wif();
        assert_eq!(&*PrivateKey::from_wif(sk).unwrap().1.to_wif(), sk);
    }

    #[test]
    fn test_import_keys_from_wif() {
        let kp =
            PrivateKey::from_wif("3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM").unwrap();
        assert_eq!(
            &*kp.1.to_wif(),
            "3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM"
        );
        assert_eq!(
            &*kp.0.to_wif(),
            "GOD52QZDBUStV5CudxvKf6bPsQeN7oeKTkEm2nAU1vAUqNVexGTb8"
        );
    }

    #[test]
    fn test_invalid_prefix() {
        let mut bytes = bs58::decode("3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM")
            .into_vec()
            .unwrap();
        bytes[0] = 255;
        let wif = bs58::encode(bytes).into_string();
        assert_eq!(
            PrivateKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidPrefix
        );

        let mut bytes = bs58::decode("52QZDBUStV5CudxvKf6bPsQeN7oeKTkEm2nAU1vAUqNVexGTb8")
            .into_vec()
            .unwrap();
        bytes[0] = 255;
        let mut wif = bs58::encode(bytes).into_string();
        wif.insert_str(0, PUB_ADDRESS_PREFIX);
        assert_eq!(
            PublicKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidPrefix
        );
    }

    #[test]
    fn test_invalid_checksum() {
        let mut bytes = bs58::decode("3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM")
            .into_vec()
            .unwrap();
        let len = bytes.len();
        for i in 1..5 {
            bytes[len - i] = 0;
        }
        let wif = bs58::encode(bytes).into_string();
        assert_eq!(
            PrivateKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidChecksum
        );

        let mut bytes = bs58::decode("52QZDBUStV5CudxvKf6bPsQeN7oeKTkEm2nAU1vAUqNVexGTb8")
            .into_vec()
            .unwrap();
        let len = bytes.len();
        for i in 1..5 {
            bytes[len - i] = 0;
        }
        let mut wif = bs58::encode(bytes).into_string();
        wif.insert_str(0, PUB_ADDRESS_PREFIX);
        assert_eq!(
            PublicKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidChecksum
        );
    }

    #[test]
    fn test_sign_message() {
        let msg = "Hello world!".as_bytes();
        let kp = KeyPair::gen_keypair();

        let sig = &kp.1.sign(msg);
        assert!(kp.0.verify(msg, sig));

        let pair = SigPair {
            pub_key: kp.0,
            signature: *sig,
        };
        assert!(pair.verify(msg));

        // Test bad keys
        let kp = KeyPair::gen_keypair();
        assert!(!kp.verify(msg, sig));
    }
}
<commit_msg>Implement Debug explicitly for PublicKey<commit_after>use bs58;
use sodiumoxide::crypto::sign;
use sodiumoxide::randombytes;
use std::fmt;

use super::error::*;
use super::sigpair::*;
use super::util::*;

pub const PUB_ADDRESS_PREFIX: &str = "GOD";
const PRIV_BUF_PREFIX: u8 = 0x01;
const PUB_BUF_PREFIX: u8 = 0x02;

pub trait Wif<T, U> {
    fn from_wif(s: &str) -> Result<T, WifError>;
    fn to_wif(&self) -> U;
}

pub struct PrivateWif(Box<str>);

impl fmt::Display for PrivateWif {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

impl std::ops::Deref for PrivateWif {
    type Target = str;

    fn deref(&self) -> &str {
        &self.0
    }
}

impl std::ops::Drop for PrivateWif {
    fn drop(&mut self) {
        let bytes = unsafe { self.0.as_bytes_mut() };
        sodiumoxide::utils::memzero(bytes);
    }
}

#[derive(Clone, PartialEq)]
pub struct PublicKey(pub(crate) sign::PublicKey);

impl PublicKey {
    #[inline]
    pub fn verify(&self, msg: &[u8], sig: &sign::Signature) -> bool {
        sign::verify_detached(sig, msg, &self.0)
    }

    #[inline]
    pub fn from_slice(bytes: &[u8]) -> Option<PublicKey> {
        let key = sign::PublicKey::from_slice(bytes)?;
        Some(PublicKey(key))
    }
}

impl Wif<PublicKey, Box<str>> for PublicKey {
    fn from_wif(s: &str) -> Result<PublicKey, WifError> {
        if s.len() < 3 || &s[0..3] != PUB_ADDRESS_PREFIX {
            return Err(WifError::new(WifErrorKind::InvalidPrefix));
        }
        let raw = match bs58::decode(&s[3..]).into_vec() {
            Ok(bytes) => bytes,
            Err(_) => {
                return Err(WifError::new(WifErrorKind::InvalidBs58Encoding));
            }
        };
        if raw.len() != 37 {
            return Err(WifError::new(WifErrorKind::InvalidLen));
        } else if raw[0] != PUB_BUF_PREFIX {
            return Err(WifError::new(WifErrorKind::InvalidPrefix));
        }

        let prefixed_key = &raw[0..raw.len() - 4];
        {
            let checksum_a = &raw[raw.len() - 4..raw.len()];
            let checksum_b = &double_sha256(prefixed_key)[0..4];
            if checksum_a != checksum_b {
                return Err(WifError::new(WifErrorKind::InvalidChecksum));
            }
        }

        let key = &prefixed_key[1..prefixed_key.len()];
        Ok(PublicKey(sign::PublicKey::from_slice(key).unwrap()))
    }

    fn to_wif(&self) -> Box<str> {
        let mut buf: Vec<u8> = Vec::<u8>::with_capacity(37);
        buf.push(PUB_BUF_PREFIX);
        buf.extend_from_slice(self.0.as_ref());

        let checksum = &double_sha256(&buf)[0..4];
        buf.extend_from_slice(checksum);

        let mut s = bs58::encode(buf).into_string();
        s.insert_str(0, PUB_ADDRESS_PREFIX);
        s.into_boxed_str()
    }
}

impl AsRef<[u8]> for PublicKey {
    fn as_ref(&self) -> &[u8] {
        self.0.as_ref()
    }
}

impl fmt::Debug for PublicKey {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, f)
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct PrivateKey {
    seed: sign::Seed,
    key: sign::SecretKey,
}

impl PrivateKey {
    #[inline]
    pub fn sign(&self, msg: &[u8]) -> sign::Signature {
        sign::sign_detached(msg, &self.key)
    }

    #[inline]
    pub fn from_slice(seed: &[u8], key: &[u8]) -> Option<PrivateKey> {
        Some(PrivateKey {
            seed: sign::Seed::from_slice(seed)?,
            key: sign::SecretKey::from_slice(key)?,
        })
    }
}

impl Wif<KeyPair, PrivateWif> for PrivateKey {
    fn from_wif(s: &str) -> Result<KeyPair, WifError> {
        let raw = match bs58::decode(s).into_vec() {
            Ok(bytes) => bytes,
            Err(_) => {
                return Err(WifError::new(WifErrorKind::InvalidBs58Encoding));
            }
        };
        if raw.len() != 37 {
            return Err(WifError::new(WifErrorKind::InvalidLen));
        } else if raw[0] != PRIV_BUF_PREFIX {
            return Err(WifError::new(WifErrorKind::InvalidPrefix));
        }

        let key = &raw[0..raw.len() - 4];
        {
            let checksum_a = &raw[raw.len() - 4..raw.len()];
            let checksum_b = &double_sha256(key)[0..4];
            if checksum_a != checksum_b {
                return Err(WifError::new(WifErrorKind::InvalidChecksum));
            }
        }

        let seed = sign::Seed::from_slice(&key[1..]).unwrap();
        let (pk, sk) = sign::keypair_from_seed(&seed);
        Ok(KeyPair(PublicKey(pk), PrivateKey { seed, key: sk }))
    }

    fn to_wif(&self) -> PrivateWif {
        let mut buf = Vec::<u8>::with_capacity(37);
        buf.push(PRIV_BUF_PREFIX);
        buf.extend_from_slice(&self.seed.0);

        let checksum = &double_sha256(&buf)[0..4];
        buf.extend_from_slice(checksum);

        PrivateWif(bs58::encode(buf).into_string().into_boxed_str())
    }
}

#[derive(Debug, Clone)]
pub struct KeyPair(pub PublicKey, pub PrivateKey);

impl KeyPair {
    #[inline]
    pub fn sign(&self, msg: &[u8]) -> SigPair {
        SigPair {
            pub_key: self.0.clone(),
            signature: self.1.sign(msg),
        }
    }

    #[inline]
    pub fn verify(&self, msg: &[u8], sig: &sign::Signature) -> bool {
        PublicKey::verify(&self.0, msg, sig)
    }

    pub fn gen_keypair() -> KeyPair {
        let mut raw_seed: [u8; sign::SEEDBYTES] = [0; sign::SEEDBYTES];
        randombytes::randombytes_into(&mut raw_seed);
        let seed = sign::Seed::from_slice(&raw_seed).unwrap();
        let (pk, sk) = sign::keypair_from_seed(&seed);
        KeyPair(PublicKey(pk), PrivateKey { seed, key: sk })
    }
}

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

    #[test]
    fn test_create_and_recover_keys() {
        let kp = KeyPair::gen_keypair();

        let pk = &*kp.0.to_wif();
        assert_eq!(&*PublicKey::from_wif(pk).unwrap().to_wif(), pk);

        let sk = &*kp.1.to_wif();
        assert_eq!(&*PrivateKey::from_wif(sk).unwrap().1.to_wif(), sk);
    }

    #[test]
    fn test_import_keys_from_wif() {
        let kp =
            PrivateKey::from_wif("3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM").unwrap();
        assert_eq!(
            &*kp.1.to_wif(),
            "3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM"
        );
        assert_eq!(
            &*kp.0.to_wif(),
            "GOD52QZDBUStV5CudxvKf6bPsQeN7oeKTkEm2nAU1vAUqNVexGTb8"
        );
    }

    #[test]
    fn test_invalid_prefix() {
        let mut bytes = bs58::decode("3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM")
            .into_vec()
            .unwrap();
        bytes[0] = 255;
        let wif = bs58::encode(bytes).into_string();
        assert_eq!(
            PrivateKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidPrefix
        );

        let mut bytes = bs58::decode("52QZDBUStV5CudxvKf6bPsQeN7oeKTkEm2nAU1vAUqNVexGTb8")
            .into_vec()
            .unwrap();
        bytes[0] = 255;
        let mut wif = bs58::encode(bytes).into_string();
        wif.insert_str(0, PUB_ADDRESS_PREFIX);
        assert_eq!(
            PublicKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidPrefix
        );
    }

    #[test]
    fn test_invalid_checksum() {
        let mut bytes = bs58::decode("3GAD3otqozDorfu1iDpMQJ1gzWp8PRFEjVHZivZdedKW3i3KtM")
            .into_vec()
            .unwrap();
        let len = bytes.len();
        for i in 1..5 {
            bytes[len - i] = 0;
        }
        let wif = bs58::encode(bytes).into_string();
        assert_eq!(
            PrivateKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidChecksum
        );

        let mut bytes = bs58::decode("52QZDBUStV5CudxvKf6bPsQeN7oeKTkEm2nAU1vAUqNVexGTb8")
            .into_vec()
            .unwrap();
        let len = bytes.len();
        for i in 1..5 {
            bytes[len - i] = 0;
        }
        let mut wif = bs58::encode(bytes).into_string();
        wif.insert_str(0, PUB_ADDRESS_PREFIX);
        assert_eq!(
            PublicKey::from_wif(&wif).unwrap_err().kind,
            WifErrorKind::InvalidChecksum
        );
    }

    #[test]
    fn test_sign_message() {
        let msg = "Hello world!".as_bytes();
        let kp = KeyPair::gen_keypair();

        let sig = &kp.1.sign(msg);
        assert!(kp.0.verify(msg, sig));

        let pair = SigPair {
            pub_key: kp.0,
            signature: *sig,
        };
        assert!(pair.verify(msg));

        // Test bad keys
        let kp = KeyPair::gen_keypair();
        assert!(!kp.verify(msg, sig));
    }
}
<|endoftext|>


<commit_before>//! Algorithm citation:
//! A Simple, Fast Dominance Algorithm.
//! Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy
//! Rice Computer Science TS-06-33870
//! <https://www.cs.rice.edu/~keith/EMBED/dom.pdf>

use super::super::indexed_vec::{Idx, IndexVec};
use super::iterate::reverse_post_order;
use super::ControlFlowGraph;

use std::fmt;

#[cfg(test)]
mod test;

pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
    let start_node = graph.start_node();
    let rpo = reverse_post_order(graph, start_node);
    dominators_given_rpo(graph, &rpo)
}

pub fn dominators_given_rpo<G: ControlFlowGraph>(
    graph: &G,
    rpo: &[G::Node],
) -> Dominators<G::Node> {
    let start_node = graph.start_node();
    assert_eq!(rpo[0], start_node);

    // compute the post order index (rank) for each node
    let mut post_order_rank: IndexVec<G::Node, usize> =
        (0..graph.num_nodes()).map(|_| 0).collect();
    for (index, node) in rpo.iter().rev().cloned().enumerate() {
        post_order_rank[node] = index;
    }

    let mut immediate_dominators: IndexVec<G::Node, Option<G::Node>> =
        (0..graph.num_nodes()).map(|_| None).collect();
    immediate_dominators[start_node] = Some(start_node);

    let mut changed = true;
    while changed {
        changed = false;

        for &node in &rpo[1..] {
            let mut new_idom = None;
            for pred in graph.predecessors(node) {
                if immediate_dominators[pred].is_some() {
                    // (*)
                    // (*) dominators for `pred` have been calculated
                    new_idom = intersect_opt(
                        &post_order_rank,
                        &immediate_dominators,
                        new_idom,
                        Some(pred),
                    );
                }
            }

            if new_idom != immediate_dominators[node] {
                immediate_dominators[node] = new_idom;
                changed = true;
            }
        }
    }

    Dominators {
        post_order_rank,
        immediate_dominators,
    }
}

fn intersect_opt<Node: Idx>(
    post_order_rank: &IndexVec<Node, usize>,
    immediate_dominators: &IndexVec<Node, Option<Node>>,
    node1: Option<Node>,
    node2: Option<Node>,
) -> Option<Node> {
    match (node1, node2) {
        (None, None) => None,
        (Some(n), None) | (None, Some(n)) => Some(n),
        (Some(n1), Some(n2)) => Some(intersect(post_order_rank, immediate_dominators, n1, n2)),
    }
}

fn intersect<Node: Idx>(
    post_order_rank: &IndexVec<Node, usize>,
    immediate_dominators: &IndexVec<Node, Option<Node>>,
    mut node1: Node,
    mut node2: Node,
) -> Node {
    while node1 != node2 {
        while post_order_rank[node1] < post_order_rank[node2] {
            node1 = immediate_dominators[node1].unwrap();
        }

        while post_order_rank[node2] < post_order_rank[node1] {
            node2 = immediate_dominators[node2].unwrap();
        }
    }

    node1
}

#[derive(Clone, Debug)]
pub struct Dominators<N: Idx> {
    post_order_rank: IndexVec<N, usize>,
    immediate_dominators: IndexVec<N, Option<N>>,
}

impl<Node: Idx> Dominators<Node> {
    pub fn is_reachable(&self, node: Node) -> bool {
        self.immediate_dominators[node].is_some()
    }

    pub fn immediate_dominator(&self, node: Node) -> Node {
        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
        self.immediate_dominators[node].unwrap()
    }

    pub fn dominators(&self, node: Node) -> Iter<'_, Node> {
        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
        Iter {
            dominators: self,
            node: Some(node),
        }
    }

    pub fn is_dominated_by(&self, node: Node, dom: Node) -> bool {
        // FIXME -- could be optimized by using post-order-rank
        self.dominators(node).any(|n| n == dom)
    }

    #[cfg(test)]
    fn all_immediate_dominators(&self) -> &IndexVec<Node, Option<Node>> {
        &self.immediate_dominators
    }
}

pub struct Iter<'dom, Node: Idx> {
    dominators: &'dom Dominators<Node>,
    node: Option<Node>,
}

impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
    type Item = Node;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(node) = self.node {
            let dom = self.dominators.immediate_dominator(node);
            if dom == node {
                self.node = None; // reached the root
            } else {
                self.node = Some(dom);
            }
            return Some(node);
        } else {
            return None;
        }
    }
}

pub struct DominatorTree<N: Idx> {
    root: N,
    children: IndexVec<N, Vec<N>>,
}

impl<Node: Idx> DominatorTree<Node> {
    pub fn children(&self, node: Node) -> &[Node] {
        &self.children[node]
    }
}

impl<Node: Idx> fmt::Debug for DominatorTree<Node> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Debug::fmt(
            &DominatorTreeNode {
                tree: self,
                node: self.root,
            },
            fmt,
        )
    }
}

struct DominatorTreeNode<'tree, Node: Idx> {
    tree: &'tree DominatorTree<Node>,
    node: Node,
}

impl<'tree, Node: Idx> fmt::Debug for DominatorTreeNode<'tree, Node> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let subtrees: Vec<_> = self.tree
            .children(self.node)
            .iter()
            .map(|&child| DominatorTreeNode {
                tree: self.tree,
                node: child,
            })
            .collect();
        fmt.debug_tuple("")
            .field(&self.node)
            .field(&subtrees)
            .finish()
    }
}
<commit_msg>Rollup merge of #59811 - vext01:dead-dominator-code, r=oli-obk<commit_after>//! Algorithm citation:
//! A Simple, Fast Dominance Algorithm.
//! Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy
//! Rice Computer Science TS-06-33870
//! <https://www.cs.rice.edu/~keith/EMBED/dom.pdf>

use super::super::indexed_vec::{Idx, IndexVec};
use super::iterate::reverse_post_order;
use super::ControlFlowGraph;

#[cfg(test)]
mod test;

pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
    let start_node = graph.start_node();
    let rpo = reverse_post_order(graph, start_node);
    dominators_given_rpo(graph, &rpo)
}

pub fn dominators_given_rpo<G: ControlFlowGraph>(
    graph: &G,
    rpo: &[G::Node],
) -> Dominators<G::Node> {
    let start_node = graph.start_node();
    assert_eq!(rpo[0], start_node);

    // compute the post order index (rank) for each node
    let mut post_order_rank: IndexVec<G::Node, usize> =
        (0..graph.num_nodes()).map(|_| 0).collect();
    for (index, node) in rpo.iter().rev().cloned().enumerate() {
        post_order_rank[node] = index;
    }

    let mut immediate_dominators: IndexVec<G::Node, Option<G::Node>> =
        (0..graph.num_nodes()).map(|_| None).collect();
    immediate_dominators[start_node] = Some(start_node);

    let mut changed = true;
    while changed {
        changed = false;

        for &node in &rpo[1..] {
            let mut new_idom = None;
            for pred in graph.predecessors(node) {
                if immediate_dominators[pred].is_some() {
                    // (*)
                    // (*) dominators for `pred` have been calculated
                    new_idom = intersect_opt(
                        &post_order_rank,
                        &immediate_dominators,
                        new_idom,
                        Some(pred),
                    );
                }
            }

            if new_idom != immediate_dominators[node] {
                immediate_dominators[node] = new_idom;
                changed = true;
            }
        }
    }

    Dominators {
        post_order_rank,
        immediate_dominators,
    }
}

fn intersect_opt<Node: Idx>(
    post_order_rank: &IndexVec<Node, usize>,
    immediate_dominators: &IndexVec<Node, Option<Node>>,
    node1: Option<Node>,
    node2: Option<Node>,
) -> Option<Node> {
    match (node1, node2) {
        (None, None) => None,
        (Some(n), None) | (None, Some(n)) => Some(n),
        (Some(n1), Some(n2)) => Some(intersect(post_order_rank, immediate_dominators, n1, n2)),
    }
}

fn intersect<Node: Idx>(
    post_order_rank: &IndexVec<Node, usize>,
    immediate_dominators: &IndexVec<Node, Option<Node>>,
    mut node1: Node,
    mut node2: Node,
) -> Node {
    while node1 != node2 {
        while post_order_rank[node1] < post_order_rank[node2] {
            node1 = immediate_dominators[node1].unwrap();
        }

        while post_order_rank[node2] < post_order_rank[node1] {
            node2 = immediate_dominators[node2].unwrap();
        }
    }

    node1
}

#[derive(Clone, Debug)]
pub struct Dominators<N: Idx> {
    post_order_rank: IndexVec<N, usize>,
    immediate_dominators: IndexVec<N, Option<N>>,
}

impl<Node: Idx> Dominators<Node> {
    pub fn is_reachable(&self, node: Node) -> bool {
        self.immediate_dominators[node].is_some()
    }

    pub fn immediate_dominator(&self, node: Node) -> Node {
        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
        self.immediate_dominators[node].unwrap()
    }

    pub fn dominators(&self, node: Node) -> Iter<'_, Node> {
        assert!(self.is_reachable(node), "node {:?} is not reachable", node);
        Iter {
            dominators: self,
            node: Some(node),
        }
    }

    pub fn is_dominated_by(&self, node: Node, dom: Node) -> bool {
        // FIXME -- could be optimized by using post-order-rank
        self.dominators(node).any(|n| n == dom)
    }

    #[cfg(test)]
    fn all_immediate_dominators(&self) -> &IndexVec<Node, Option<Node>> {
        &self.immediate_dominators
    }
}

pub struct Iter<'dom, Node: Idx> {
    dominators: &'dom Dominators<Node>,
    node: Option<Node>,
}

impl<'dom, Node: Idx> Iterator for Iter<'dom, Node> {
    type Item = Node;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(node) = self.node {
            let dom = self.dominators.immediate_dominator(node);
            if dom == node {
                self.node = None; // reached the root
            } else {
                self.node = Some(dom);
            }
            return Some(node);
        } else {
            return None;
        }
    }
}
<|endoftext|>