<commit_before>extern crate regex;

use self::regex::Regex;
use crate::common::util::*;
#[cfg(all(unix, not(target_os = "macos")))]
use rust_users::*;

#[test]
fn test_date_email() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--rfc-email").run();
    assert!(result.success);
}

#[test]
fn test_date_email2() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("-R").run();
    assert!(result.success);
}

#[test]
fn test_date_rfc_3339() {
    let scene = TestScenario::new(util_name!());

    let mut result = scene.ucmd().arg("--rfc-3339=ns").succeeds();

    // Check that the output matches the regexp
    let rfc_regexp = r"(\d+)-(0[1-9]|1[012])-(0[1-9]|[12]\d|3[01])\s([01]\d|2[0-3]):([0-5]\d):([0-5]\d|60)(\.\d+)?(([Zz])|([\+|\-]([01]\d|2[0-3])))";
    let re = Regex::new(rfc_regexp).unwrap();
    assert!(re.is_match(&result.stdout.trim()));

    result = scene.ucmd().arg("--rfc-3339=seconds").succeeds();

    // Check that the output matches the regexp
    let re = Regex::new(rfc_regexp).unwrap();
    assert!(re.is_match(&result.stdout.trim()));
}

#[test]
fn test_date_rfc_8601() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--iso-8601=ns").run();
    assert!(result.success);
}

#[test]
fn test_date_rfc_8601_second() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--iso-8601=second").run();
    assert!(result.success);
}

#[test]
fn test_date_utc() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--utc").run();
    assert!(result.success);
}

#[test]
fn test_date_universal() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--universal").run();
    assert!(result.success);
}

#[test]
fn test_date_format_y() {
    let scene = TestScenario::new(util_name!());

    let mut result = scene.ucmd().arg("+%Y").succeeds();

    assert!(result.success);
    let mut re = Regex::new(r"^\d{4}$").unwrap();
    assert!(re.is_match(&result.stdout.trim()));

    result = scene.ucmd().arg("+%y").succeeds();

    assert!(result.success);
    re = Regex::new(r"^\d{2}$").unwrap();
    assert!(re.is_match(&result.stdout.trim()));
}

#[test]
fn test_date_format_m() {
    let scene = TestScenario::new(util_name!());

    let mut result = scene.ucmd().arg("+%b").succeeds();

    assert!(result.success);
    let mut re = Regex::new(r"\S+").unwrap();
    assert!(re.is_match(&result.stdout.trim()));

    result = scene.ucmd().arg("+%m").succeeds();

    assert!(result.success);
    re = Regex::new(r"^\d{2}$").unwrap();
    assert!(re.is_match(&result.stdout.trim()));
}

#[test]
fn test_date_format_day() {
    let scene = TestScenario::new(util_name!());

    let mut result = scene.ucmd().arg("+%a").succeeds();

    assert!(result.success);
    let mut re = Regex::new(r"\S+").unwrap();
    assert!(re.is_match(&result.stdout.trim()));

    result = scene.ucmd().arg("+%A").succeeds();

    assert!(result.success);

    re = Regex::new(r"\S+").unwrap();
    assert!(re.is_match(&result.stdout.trim()));

    result = scene.ucmd().arg("+%u").succeeds();

    assert!(result.success);
    re = Regex::new(r"^\d{1}$").unwrap();
    assert!(re.is_match(&result.stdout.trim()));
}

#[test]
fn test_date_format_full_day() {
    let scene = TestScenario::new(util_name!());

    let result = scene.ucmd().arg("+'%a %Y-%m-%d'").succeeds();

    assert!(result.success);
    let re = Regex::new(r"\S+ \d{4}-\d{2}-\d{2}").unwrap();
    assert!(re.is_match(&result.stdout.trim()));
}

#[test]
#[cfg(all(unix, not(target_os = "macos")))]
fn test_date_set_valid() {
    if get_effective_uid() == 0 {
        let (_, mut ucmd) = at_and_ucmd!();
        let result = ucmd.arg("--set").arg("2020-03-12 13:30:00+08:00").succeeds();
        result.no_stdout().no_stderr();
    }
}

#[test]
#[cfg(any(windows, all(unix, not(target_os = "macos"))))]
fn test_date_set_invalid() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--set").arg("123abcd").fails();
    let result = result.no_stdout();
    assert!(result.stderr.starts_with("date: invalid date "));
}

#[test]
#[cfg(all(unix, not(target_os = "macos")))]
fn test_date_set_permissions_error() {
    if !(get_effective_uid() == 0 || is_wsl()) {
        let (_, mut ucmd) = at_and_ucmd!();
        let result = ucmd.arg("--set").arg("2020-03-11 21:45:00+08:00").fails();
        let result = result.no_stdout();
        assert!(result.stderr.starts_with("date: cannot set date: "));
    }
}

#[test]
#[cfg(target_os = "macos")]
fn test_date_set_mac_unavailable() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--set").arg("2020-03-11 21:45:00+08:00").fails();
    let result = result.no_stdout();
    assert!(result.stderr.starts_with("date: setting the date is not supported by macOS"));
}
<commit_msg>Rustfmt the tests<commit_after>extern crate regex;

use self::regex::Regex;
use crate::common::util::*;
#[cfg(all(unix, not(target_os = "macos")))]
use rust_users::*;

#[test]
fn test_date_email() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--rfc-email").run();
    assert!(result.success);
}

#[test]
fn test_date_email2() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("-R").run();
    assert!(result.success);
}

#[test]
fn test_date_rfc_3339() {
    let scene = TestScenario::new(util_name!());

    let mut result = scene.ucmd().arg("--rfc-3339=ns").succeeds();

    // Check that the output matches the regexp
    let rfc_regexp = r"(\d+)-(0[1-9]|1[012])-(0[1-9]|[12]\d|3[01])\s([01]\d|2[0-3]):([0-5]\d):([0-5]\d|60)(\.\d+)?(([Zz])|([\+|\-]([01]\d|2[0-3])))";
    let re = Regex::new(rfc_regexp).unwrap();
    assert!(re.is_match(&result.stdout.trim()));

    result = scene.ucmd().arg("--rfc-3339=seconds").succeeds();

    // Check that the output matches the regexp
    let re = Regex::new(rfc_regexp).unwrap();
    assert!(re.is_match(&result.stdout.trim()));
}

#[test]
fn test_date_rfc_8601() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--iso-8601=ns").run();
    assert!(result.success);
}

#[test]
fn test_date_rfc_8601_second() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--iso-8601=second").run();
    assert!(result.success);
}

#[test]
fn test_date_utc() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--utc").run();
    assert!(result.success);
}

#[test]
fn test_date_universal() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--universal").run();
    assert!(result.success);
}

#[test]
fn test_date_format_y() {
    let scene = TestScenario::new(util_name!());

    let mut result = scene.ucmd().arg("+%Y").succeeds();

    assert!(result.success);
    let mut re = Regex::new(r"^\d{4}$").unwrap();
    assert!(re.is_match(&result.stdout.trim()));

    result = scene.ucmd().arg("+%y").succeeds();

    assert!(result.success);
    re = Regex::new(r"^\d{2}$").unwrap();
    assert!(re.is_match(&result.stdout.trim()));
}

#[test]
fn test_date_format_m() {
    let scene = TestScenario::new(util_name!());

    let mut result = scene.ucmd().arg("+%b").succeeds();

    assert!(result.success);
    let mut re = Regex::new(r"\S+").unwrap();
    assert!(re.is_match(&result.stdout.trim()));

    result = scene.ucmd().arg("+%m").succeeds();

    assert!(result.success);
    re = Regex::new(r"^\d{2}$").unwrap();
    assert!(re.is_match(&result.stdout.trim()));
}

#[test]
fn test_date_format_day() {
    let scene = TestScenario::new(util_name!());

    let mut result = scene.ucmd().arg("+%a").succeeds();

    assert!(result.success);
    let mut re = Regex::new(r"\S+").unwrap();
    assert!(re.is_match(&result.stdout.trim()));

    result = scene.ucmd().arg("+%A").succeeds();

    assert!(result.success);

    re = Regex::new(r"\S+").unwrap();
    assert!(re.is_match(&result.stdout.trim()));

    result = scene.ucmd().arg("+%u").succeeds();

    assert!(result.success);
    re = Regex::new(r"^\d{1}$").unwrap();
    assert!(re.is_match(&result.stdout.trim()));
}

#[test]
fn test_date_format_full_day() {
    let scene = TestScenario::new(util_name!());

    let result = scene.ucmd().arg("+'%a %Y-%m-%d'").succeeds();

    assert!(result.success);
    let re = Regex::new(r"\S+ \d{4}-\d{2}-\d{2}").unwrap();
    assert!(re.is_match(&result.stdout.trim()));
}

#[test]
#[cfg(all(unix, not(target_os = "macos")))]
fn test_date_set_valid() {
    if get_effective_uid() == 0 {
        let (_, mut ucmd) = at_and_ucmd!();
        let result = ucmd
            .arg("--set")
            .arg("2020-03-12 13:30:00+08:00")
            .succeeds();
        result.no_stdout().no_stderr();
    }
}

#[test]
#[cfg(any(windows, all(unix, not(target_os = "macos"))))]
fn test_date_set_invalid() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--set").arg("123abcd").fails();
    let result = result.no_stdout();
    assert!(result.stderr.starts_with("date: invalid date "));
}

#[test]
#[cfg(all(unix, not(target_os = "macos")))]
fn test_date_set_permissions_error() {
    if !(get_effective_uid() == 0 || is_wsl()) {
        let (_, mut ucmd) = at_and_ucmd!();
        let result = ucmd.arg("--set").arg("2020-03-11 21:45:00+08:00").fails();
        let result = result.no_stdout();
        assert!(result.stderr.starts_with("date: cannot set date: "));
    }
}

#[test]
#[cfg(target_os = "macos")]
fn test_date_set_mac_unavailable() {
    let (_, mut ucmd) = at_and_ucmd!();
    let result = ucmd.arg("--set").arg("2020-03-11 21:45:00+08:00").fails();
    let result = result.no_stdout();
    assert!(result
        .stderr
        .starts_with("date: setting the date is not supported by macOS"));
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

extern crate regex;

use crate::common::util::*;

extern crate stat;
pub use self::stat::*;

#[test]
fn test_scanners() {
    assert_eq!(Some((-5, 2)), "-5zxc".scan_num::<i32>());
    assert_eq!(Some((51, 2)), "51zxc".scan_num::<u32>());
    assert_eq!(Some((192, 4)), "+192zxc".scan_num::<i32>());
    assert_eq!(None, "z192zxc".scan_num::<i32>());

    assert_eq!(Some(('a', 3)), "141zxc".scan_char(8));
    assert_eq!(Some(('\n', 2)), "12qzxc".scan_char(8)); // spell-checker:disable-line
    assert_eq!(Some(('\r', 1)), "dqzxc".scan_char(16)); // spell-checker:disable-line
    assert_eq!(None, "z2qzxc".scan_char(8)); // spell-checker:disable-line
}

#[test]
fn test_group_num() {
    assert_eq!("12,379,821,234", group_num("12379821234"));
    assert_eq!("21,234", group_num("21234"));
    assert_eq!("821,234", group_num("821234"));
    assert_eq!("1,821,234", group_num("1821234"));
    assert_eq!("1,234", group_num("1234"));
    assert_eq!("234", group_num("234"));
    assert_eq!("24", group_num("24"));
    assert_eq!("4", group_num("4"));
    assert_eq!("", group_num(""));
}

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

    #[test]
    fn normal_format() {
        let s = "%'010.2ac%-#5.w\n";
        let expected = vec![
            Token::Directive {
                flag: F_GROUP | F_ZERO,
                width: 10,
                precision: 2,
                format: 'a',
            },
            Token::Char('c'),
            Token::Directive {
                flag: F_LEFT | F_ALTER,
                width: 5,
                precision: 0,
                format: 'w',
            },
            Token::Char('\n'),
        ];
        assert_eq!(&expected, &Stater::generate_tokens(s, false).unwrap());
    }

    #[test]
    fn printf_format() {
        let s = "%-# 15a\\t\\r\\\"\\\\\\a\\b\\e\\f\\v%+020.-23w\\x12\\167\\132\\112\\n";
        let expected = vec![
            Token::Directive {
                flag: F_LEFT | F_ALTER | F_SPACE,
                width: 15,
                precision: -1,
                format: 'a',
            },
            Token::Char('\t'),
            Token::Char('\r'),
            Token::Char('"'),
            Token::Char('\\'),
            Token::Char('\x07'),
            Token::Char('\x08'),
            Token::Char('\x1B'),
            Token::Char('\x0C'),
            Token::Char('\x0B'),
            Token::Directive {
                flag: F_SIGN | F_ZERO,
                width: 20,
                precision: -1,
                format: 'w',
            },
            Token::Char('\x12'),
            Token::Char('w'),
            Token::Char('Z'),
            Token::Char('J'),
            Token::Char('\n'),
        ];
        assert_eq!(&expected, &Stater::generate_tokens(s, true).unwrap());
    }
}

#[test]
fn test_invalid_option() {
    new_ucmd!().arg("-w").arg("-q").arg("/").fails();
}

#[cfg(any(target_os = "linux", target_vendor = "apple"))]
const NORMAL_FORMAT_STR: &str =
    "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s %u %U %x %X %y %Y %z %Z"; // avoid "%w %W" (birth/creation) due to `stat` limitations and linux kernel & rust version capability variations
#[cfg(any(target_os = "linux"))]
const DEV_FORMAT_STR: &str =
    "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s (%t/%T) %u %U %w %W %x %X %y %Y %z %Z";
#[cfg(target_os = "linux")]
const FS_FORMAT_STR: &str = "%b %c %i %l %n %s %S %t %T"; // avoid "%a %d %f" which can cause test failure due to race conditions

#[test]
#[cfg(target_os = "linux")]
fn test_terse_fs_format() {
    let args = ["-f", "-t", "/proc"];
    let ts = TestScenario::new(util_name!());
    let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    ts.ucmd().args(&args).run().stdout_is(expected_stdout);
}

#[test]
#[cfg(target_os = "linux")]
fn test_fs_format() {
    let args = ["-f", "-c", FS_FORMAT_STR, "/dev/shm"];
    let ts = TestScenario::new(util_name!());
    let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    ts.ucmd().args(&args).run().stdout_is(expected_stdout);
}

#[cfg(unix)]
#[test]
fn test_terse_normal_format() {
    // note: contains birth/creation date which increases test fragility
    // * results may vary due to built-in `stat` limitations as well as linux kernel and rust version capability variations
    let args = ["-t", "/"];
    let ts = TestScenario::new(util_name!());
    let actual = ts.ucmd().args(&args).succeeds().stdout_move_str();
    let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    let v_actual: Vec<&str> = actual.trim().split(' ').collect();
    let mut v_expect: Vec<&str> = expect.trim().split(' ').collect();
    assert!(!v_expect.is_empty());

    // uu_stat does not support selinux
    if v_actual.len() == v_expect.len() - 1 && v_expect[v_expect.len() - 1].contains(':') {
        // assume last element contains: `SELinux security context string`
        v_expect.pop();
    }

    // * allow for inequality if `stat` (aka, expect) returns "0" (unknown value)
    assert!(
        expect == "0"
            || expect == "0\n"
            || v_actual
                .iter()
                .zip(v_expect.iter())
                .all(|(a, e)| a == e || *e == "0" || *e == "0\n")
    );
}

#[cfg(unix)]
#[test]
fn test_format_created_time() {
    let args = ["-c", "%w", "/bin"];
    let ts = TestScenario::new(util_name!());
    let actual = ts.ucmd().args(&args).succeeds().stdout_move_str();
    let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    // note: using a regex instead of `split_whitespace()` in order to detect whitespace differences
    let re = regex::Regex::new(r"\s").unwrap();
    let v_actual: Vec<&str> = re.split(&actual).collect();
    let v_expect: Vec<&str> = re.split(&expect).collect();
    assert!(!v_expect.is_empty());
    // * allow for inequality if `stat` (aka, expect) returns "-" (unknown value)
    assert!(
        expect == "-"
            || expect == "-\n"
            || v_actual
                .iter()
                .zip(v_expect.iter())
                .all(|(a, e)| a == e || *e == "-" || *e == "-\n")
    );
}

#[cfg(unix)]
#[test]
fn test_format_created_seconds() {
    let args = ["-c", "%W", "/bin"];
    let ts = TestScenario::new(util_name!());
    let actual = ts.ucmd().args(&args).succeeds().stdout_move_str();
    let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    // note: using a regex instead of `split_whitespace()` in order to detect whitespace differences
    let re = regex::Regex::new(r"\s").unwrap();
    let v_actual: Vec<&str> = re.split(&actual).collect();
    let v_expect: Vec<&str> = re.split(&expect).collect();
    assert!(!v_expect.is_empty());
    // * allow for inequality if `stat` (aka, expect) returns "0" (unknown value)
    assert!(
        expect == "0"
            || expect == "0\n"
            || v_actual
                .iter()
                .zip(v_expect.iter())
                .all(|(a, e)| a == e || *e == "0" || *e == "0\n")
    );
}

#[cfg(unix)]
#[test]
fn test_normal_format() {
    let args = ["-c", NORMAL_FORMAT_STR, "/bin"];
    let ts = TestScenario::new(util_name!());
    let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout);
}

#[cfg(unix)]
#[test]
fn test_symlinks() {
    let ts = TestScenario::new(util_name!());
    let at = &ts.fixtures;

    let mut tested: bool = false;
    // arbitrarily chosen symlinks with hope that the CI environment provides at least one of them
    for file in &[
        "/bin/sh",
        "/bin/sudoedit",
        "/usr/bin/ex",
        "/etc/localtime",
        "/etc/aliases",
    ] {
        if at.file_exists(file) && at.is_symlink(file) {
            tested = true;
            let args = ["-c", NORMAL_FORMAT_STR, file];
            let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
            ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout);
            // -L, --dereference    follow links
            let args = ["-L", "-c", NORMAL_FORMAT_STR, file];
            let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
            ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout);
        }
    }
    if !tested {
        panic!("No symlink found to test in this environment");
    }
}

#[cfg(any(target_os = "linux", target_vendor = "apple"))]
#[test]
fn test_char() {
    // TODO: "(%t) (%x) (%w)" deviate from GNU stat for `character special file` on macOS
    // Diff < left / right > :
    // <"(f0000) (2021-05-20 23:08:03.442555000 +0200) (1970-01-01 01:00:00.000000000 +0100)\n"
    // >"(f) (2021-05-20 23:08:03.455598000 +0200) (-)\n"
    let args = [
        "-c",
        #[cfg(target_os = "linux")]
        DEV_FORMAT_STR,
        #[cfg(target_os = "linux")]
        "/dev/pts/ptmx",
        #[cfg(any(target_vendor = "apple"))]
        "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s (/%T) %u %U %W %X %y %Y %z %Z",
        #[cfg(any(target_vendor = "apple"))]
        "/dev/ptmx",
    ];
    let ts = TestScenario::new(util_name!());
    let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout);
}

#[cfg(unix)]
#[test]
fn test_multi_files() {
    let args = [
        "-c",
        NORMAL_FORMAT_STR,
        "/dev",
        "/usr/lib",
        #[cfg(target_os = "linux")]
        "/etc/fstab",
        "/var",
    ];
    let ts = TestScenario::new(util_name!());
    let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout);
}

#[cfg(unix)]
#[test]
fn test_printf() {
    let args = [
        "--printf=123%-# 15q\\r\\\"\\\\\\a\\b\\e\\f\\v%+020.23m\\x12\\167\\132\\112\\n",
        "/",
    ];
    let ts = TestScenario::new(util_name!());
    let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout);
}
<commit_msg>NORMAL_FORMAT_STR is also used for freebsd<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

extern crate regex;

use crate::common::util::*;

extern crate stat;
pub use self::stat::*;

#[test]
fn test_scanners() {
    assert_eq!(Some((-5, 2)), "-5zxc".scan_num::<i32>());
    assert_eq!(Some((51, 2)), "51zxc".scan_num::<u32>());
    assert_eq!(Some((192, 4)), "+192zxc".scan_num::<i32>());
    assert_eq!(None, "z192zxc".scan_num::<i32>());

    assert_eq!(Some(('a', 3)), "141zxc".scan_char(8));
    assert_eq!(Some(('\n', 2)), "12qzxc".scan_char(8)); // spell-checker:disable-line
    assert_eq!(Some(('\r', 1)), "dqzxc".scan_char(16)); // spell-checker:disable-line
    assert_eq!(None, "z2qzxc".scan_char(8)); // spell-checker:disable-line
}

#[test]
fn test_group_num() {
    assert_eq!("12,379,821,234", group_num("12379821234"));
    assert_eq!("21,234", group_num("21234"));
    assert_eq!("821,234", group_num("821234"));
    assert_eq!("1,821,234", group_num("1821234"));
    assert_eq!("1,234", group_num("1234"));
    assert_eq!("234", group_num("234"));
    assert_eq!("24", group_num("24"));
    assert_eq!("4", group_num("4"));
    assert_eq!("", group_num(""));
}

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

    #[test]
    fn normal_format() {
        let s = "%'010.2ac%-#5.w\n";
        let expected = vec![
            Token::Directive {
                flag: F_GROUP | F_ZERO,
                width: 10,
                precision: 2,
                format: 'a',
            },
            Token::Char('c'),
            Token::Directive {
                flag: F_LEFT | F_ALTER,
                width: 5,
                precision: 0,
                format: 'w',
            },
            Token::Char('\n'),
        ];
        assert_eq!(&expected, &Stater::generate_tokens(s, false).unwrap());
    }

    #[test]
    fn printf_format() {
        let s = "%-# 15a\\t\\r\\\"\\\\\\a\\b\\e\\f\\v%+020.-23w\\x12\\167\\132\\112\\n";
        let expected = vec![
            Token::Directive {
                flag: F_LEFT | F_ALTER | F_SPACE,
                width: 15,
                precision: -1,
                format: 'a',
            },
            Token::Char('\t'),
            Token::Char('\r'),
            Token::Char('"'),
            Token::Char('\\'),
            Token::Char('\x07'),
            Token::Char('\x08'),
            Token::Char('\x1B'),
            Token::Char('\x0C'),
            Token::Char('\x0B'),
            Token::Directive {
                flag: F_SIGN | F_ZERO,
                width: 20,
                precision: -1,
                format: 'w',
            },
            Token::Char('\x12'),
            Token::Char('w'),
            Token::Char('Z'),
            Token::Char('J'),
            Token::Char('\n'),
        ];
        assert_eq!(&expected, &Stater::generate_tokens(s, true).unwrap());
    }
}

#[test]
fn test_invalid_option() {
    new_ucmd!().arg("-w").arg("-q").arg("/").fails();
}

#[cfg(unix)]
const NORMAL_FORMAT_STR: &str =
    "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s %u %U %x %X %y %Y %z %Z"; // avoid "%w %W" (birth/creation) due to `stat` limitations and linux kernel & rust version capability variations
#[cfg(any(target_os = "linux"))]
const DEV_FORMAT_STR: &str =
    "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s (%t/%T) %u %U %w %W %x %X %y %Y %z %Z";
#[cfg(target_os = "linux")]
const FS_FORMAT_STR: &str = "%b %c %i %l %n %s %S %t %T"; // avoid "%a %d %f" which can cause test failure due to race conditions

#[test]
#[cfg(target_os = "linux")]
fn test_terse_fs_format() {
    let args = ["-f", "-t", "/proc"];
    let ts = TestScenario::new(util_name!());
    let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    ts.ucmd().args(&args).run().stdout_is(expected_stdout);
}

#[test]
#[cfg(target_os = "linux")]
fn test_fs_format() {
    let args = ["-f", "-c", FS_FORMAT_STR, "/dev/shm"];
    let ts = TestScenario::new(util_name!());
    let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    ts.ucmd().args(&args).run().stdout_is(expected_stdout);
}

#[cfg(unix)]
#[test]
fn test_terse_normal_format() {
    // note: contains birth/creation date which increases test fragility
    // * results may vary due to built-in `stat` limitations as well as linux kernel and rust version capability variations
    let args = ["-t", "/"];
    let ts = TestScenario::new(util_name!());
    let actual = ts.ucmd().args(&args).succeeds().stdout_move_str();
    let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    let v_actual: Vec<&str> = actual.trim().split(' ').collect();
    let mut v_expect: Vec<&str> = expect.trim().split(' ').collect();
    assert!(!v_expect.is_empty());

    // uu_stat does not support selinux
    if v_actual.len() == v_expect.len() - 1 && v_expect[v_expect.len() - 1].contains(':') {
        // assume last element contains: `SELinux security context string`
        v_expect.pop();
    }

    // * allow for inequality if `stat` (aka, expect) returns "0" (unknown value)
    assert!(
        expect == "0"
            || expect == "0\n"
            || v_actual
                .iter()
                .zip(v_expect.iter())
                .all(|(a, e)| a == e || *e == "0" || *e == "0\n")
    );
}

#[cfg(unix)]
#[test]
fn test_format_created_time() {
    let args = ["-c", "%w", "/bin"];
    let ts = TestScenario::new(util_name!());
    let actual = ts.ucmd().args(&args).succeeds().stdout_move_str();
    let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    // note: using a regex instead of `split_whitespace()` in order to detect whitespace differences
    let re = regex::Regex::new(r"\s").unwrap();
    let v_actual: Vec<&str> = re.split(&actual).collect();
    let v_expect: Vec<&str> = re.split(&expect).collect();
    assert!(!v_expect.is_empty());
    // * allow for inequality if `stat` (aka, expect) returns "-" (unknown value)
    assert!(
        expect == "-"
            || expect == "-\n"
            || v_actual
                .iter()
                .zip(v_expect.iter())
                .all(|(a, e)| a == e || *e == "-" || *e == "-\n")
    );
}

#[cfg(unix)]
#[test]
fn test_format_created_seconds() {
    let args = ["-c", "%W", "/bin"];
    let ts = TestScenario::new(util_name!());
    let actual = ts.ucmd().args(&args).succeeds().stdout_move_str();
    let expect = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    // note: using a regex instead of `split_whitespace()` in order to detect whitespace differences
    let re = regex::Regex::new(r"\s").unwrap();
    let v_actual: Vec<&str> = re.split(&actual).collect();
    let v_expect: Vec<&str> = re.split(&expect).collect();
    assert!(!v_expect.is_empty());
    // * allow for inequality if `stat` (aka, expect) returns "0" (unknown value)
    assert!(
        expect == "0"
            || expect == "0\n"
            || v_actual
                .iter()
                .zip(v_expect.iter())
                .all(|(a, e)| a == e || *e == "0" || *e == "0\n")
    );
}

#[cfg(unix)]
#[test]
fn test_normal_format() {
    let args = ["-c", NORMAL_FORMAT_STR, "/bin"];
    let ts = TestScenario::new(util_name!());
    let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout);
}

#[cfg(unix)]
#[test]
fn test_symlinks() {
    let ts = TestScenario::new(util_name!());
    let at = &ts.fixtures;

    let mut tested: bool = false;
    // arbitrarily chosen symlinks with hope that the CI environment provides at least one of them
    for file in &[
        "/bin/sh",
        "/bin/sudoedit",
        "/usr/bin/ex",
        "/etc/localtime",
        "/etc/aliases",
    ] {
        if at.file_exists(file) && at.is_symlink(file) {
            tested = true;
            let args = ["-c", NORMAL_FORMAT_STR, file];
            let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
            ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout);
            // -L, --dereference    follow links
            let args = ["-L", "-c", NORMAL_FORMAT_STR, file];
            let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
            ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout);
        }
    }
    if !tested {
        panic!("No symlink found to test in this environment");
    }
}

#[cfg(any(target_os = "linux", target_vendor = "apple"))]
#[test]
fn test_char() {
    // TODO: "(%t) (%x) (%w)" deviate from GNU stat for `character special file` on macOS
    // Diff < left / right > :
    // <"(f0000) (2021-05-20 23:08:03.442555000 +0200) (1970-01-01 01:00:00.000000000 +0100)\n"
    // >"(f) (2021-05-20 23:08:03.455598000 +0200) (-)\n"
    let args = [
        "-c",
        #[cfg(target_os = "linux")]
        DEV_FORMAT_STR,
        #[cfg(target_os = "linux")]
        "/dev/pts/ptmx",
        #[cfg(any(target_vendor = "apple"))]
        "%a %A %b %B %d %D %f %F %g %G %h %i %m %n %o %s (/%T) %u %U %W %X %y %Y %z %Z",
        #[cfg(any(target_vendor = "apple"))]
        "/dev/ptmx",
    ];
    let ts = TestScenario::new(util_name!());
    let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout);
}

#[cfg(unix)]
#[test]
fn test_multi_files() {
    let args = [
        "-c",
        NORMAL_FORMAT_STR,
        "/dev",
        "/usr/lib",
        #[cfg(target_os = "linux")]
        "/etc/fstab",
        "/var",
    ];
    let ts = TestScenario::new(util_name!());
    let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout);
}

#[cfg(unix)]
#[test]
fn test_printf() {
    let args = [
        "--printf=123%-# 15q\\r\\\"\\\\\\a\\b\\e\\f\\v%+020.23m\\x12\\167\\132\\112\\n",
        "/",
    ];
    let ts = TestScenario::new(util_name!());
    let expected_stdout = unwrap_or_return!(expected_result(&ts, &args)).stdout_move_str();
    ts.ucmd().args(&args).succeeds().stdout_is(expected_stdout);
}
<|endoftext|>


<commit_before>#[cfg(all(test, feature = "smtp-transport", feature = "r2d2"))]
mod sync {
    use lettre::{address::Envelope, SmtpTransport, Transport};
    use std::{sync::mpsc, thread};

    fn envelope() -> Envelope {
        Envelope::new(
            Some("user@localhost".parse().unwrap()),
            vec!["root@localhost".parse().unwrap()],
        )
        .unwrap()
    }

    #[test]
    fn send_one() {
        let mailer = SmtpTransport::builder_dangerous("127.0.0.1")
            .port(2525)
            .build();

        let result = mailer.send_raw(&envelope(), b"test");
        assert!(result.is_ok());
    }

    #[test]
    fn send_from_thread() {
        let mailer = SmtpTransport::builder_dangerous("127.0.0.1")
            .port(2525)
            .build();

        let (s1, r1) = mpsc::channel();
        let (s2, r2) = mpsc::channel();

        let mailer1 = mailer.clone();
        let t1 = thread::spawn(move || {
            s1.send(()).unwrap();
            r2.recv().unwrap();
            mailer1
                .send_raw(&envelope(), b"test1")
                .expect("Send failed from thread 1");
        });

        let mailer2 = mailer.clone();
        let t2 = thread::spawn(move || {
            s2.send(()).unwrap();
            r1.recv().unwrap();
            mailer2
                .send_raw(&envelope(), b"test2")
                .expect("Send failed from thread 2");
        });

        t1.join().unwrap();
        t2.join().unwrap();

        mailer
            .send_raw(&envelope(), b"test")
            .expect("Send failed from main thread");
    }
}
<commit_msg>Re-enable pool tests (#684)<commit_after>#[cfg(all(test, feature = "smtp-transport", feature = "pool"))]
mod sync {
    use lettre::{address::Envelope, SmtpTransport, Transport};
    use std::{sync::mpsc, thread};

    fn envelope() -> Envelope {
        Envelope::new(
            Some("user@localhost".parse().unwrap()),
            vec!["root@localhost".parse().unwrap()],
        )
        .unwrap()
    }

    #[test]
    fn send_one() {
        let mailer = SmtpTransport::builder_dangerous("127.0.0.1")
            .port(2525)
            .build();

        let result = mailer.send_raw(&envelope(), b"test");
        assert!(result.is_ok());
    }

    #[test]
    fn send_from_thread() {
        let mailer = SmtpTransport::builder_dangerous("127.0.0.1")
            .port(2525)
            .build();

        let (s1, r1) = mpsc::channel();
        let (s2, r2) = mpsc::channel();

        let mailer1 = mailer.clone();
        let t1 = thread::spawn(move || {
            s1.send(()).unwrap();
            r2.recv().unwrap();
            mailer1
                .send_raw(&envelope(), b"test1")
                .expect("Send failed from thread 1");
        });

        let mailer2 = mailer.clone();
        let t2 = thread::spawn(move || {
            s2.send(()).unwrap();
            r1.recv().unwrap();
            mailer2
                .send_raw(&envelope(), b"test2")
                .expect("Send failed from thread 2");
        });

        t1.join().unwrap();
        t2.join().unwrap();

        mailer
            .send_raw(&envelope(), b"test")
            .expect("Send failed from main thread");
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(dead_code)]
#![warn(clippy::unused_io_amount)]

use std::io;

// FIXME: compiletest doesn't understand errors from macro invocation span
fn try_macro<T: io::Read + io::Write>(s: &mut T) -> io::Result<()> {
    try!(s.write(b"test"));
    let mut buf = [0u8; 4];
    try!(s.read(&mut buf));
    Ok(())
}

fn question_mark<T: io::Read + io::Write>(s: &mut T) -> io::Result<()> {
    s.write(b"test")?;
    let mut buf = [0u8; 4];
    s.read(&mut buf)?;
    Ok(())
}

fn unwrap<T: io::Read + io::Write>(s: &mut T) {
    s.write(b"test").unwrap();
    let mut buf = [0u8; 4];
    s.read(&mut buf).unwrap();
}

fn main() {}
<commit_msg>Remove obsolete comment<commit_after>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(dead_code)]
#![warn(clippy::unused_io_amount)]

use std::io;

fn try_macro<T: io::Read + io::Write>(s: &mut T) -> io::Result<()> {
    try!(s.write(b"test"));
    let mut buf = [0u8; 4];
    try!(s.read(&mut buf));
    Ok(())
}

fn question_mark<T: io::Read + io::Write>(s: &mut T) -> io::Result<()> {
    s.write(b"test")?;
    let mut buf = [0u8; 4];
    s.read(&mut buf)?;
    Ok(())
}

fn unwrap<T: io::Read + io::Write>(s: &mut T) {
    s.write(b"test").unwrap();
    let mut buf = [0u8; 4];
    s.read(&mut buf).unwrap();
}

fn main() {}
<|endoftext|>


<commit_before>use crate::{AssistContext, AssistId, Assists};
use ra_syntax::{ast, ast::{TypeParamsOwner}, AstNode, SyntaxKind};

/// Assist: change_lifetime_anon_to_named
///
/// Change an anonymous lifetime to a named lifetime.
///
/// ```
/// impl Cursor<'_<|>> {
///     fn node(self) -> &SyntaxNode {
///         match self {
///             Cursor::Replace(node) | Cursor::Before(node) => node,
///         }
///     }
/// }
/// ```
/// ->
/// ```
/// impl<'a> Cursor<'a> {
///     fn node(self) -> &SyntaxNode {
///         match self {
///             Cursor::Replace(node) | Cursor::Before(node) => node,
///         }
///     }
/// }
/// ```
// TODO : How can we handle renaming any one of multiple anonymous lifetimes?
pub(crate) fn change_lifetime_anon_to_named(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let lifetime_token = ctx.find_token_at_offset(SyntaxKind::LIFETIME)?;
    let lifetime_arg = ast::LifetimeArg::cast(lifetime_token.parent())?;
    if lifetime_arg.syntax().text() != "'_" {
        return None;
    }
    let next_token = lifetime_token.next_token()?;
    if next_token.kind() != SyntaxKind::R_ANGLE {
        // only allow naming the last anonymous lifetime
        return None;
    }
    match lifetime_arg.syntax().ancestors().find_map(ast::ImplDef::cast) {
        Some(impl_def) => {
            // get the `impl` keyword so we know where to add the lifetime argument
            let impl_kw = impl_def.syntax().first_child_or_token()?.into_token()?;
            if impl_kw.kind() != SyntaxKind::IMPL_KW {
                return None;
            }
            acc.add(
                AssistId("change_lifetime_anon_to_named"),
                "Give anonymous lifetime a name",
                lifetime_arg.syntax().text_range(),
                |builder| {
                    match impl_def.type_param_list() {
                        Some(type_params) => {
                            builder.insert(
                                (u32::from(type_params.syntax().text_range().end()) - 1).into(),
                                ", 'a",
                            );
                        },
                        None => {
                            builder.insert(
                                impl_kw.text_range().end(),
                                "<'a>",
                            );
                        },
                    }
                    builder.replace(lifetime_arg.syntax().text_range(), "'a");
                },
            )
        }
        _ => None,
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::tests::{check_assist, check_assist_not_applicable};

    #[test]
    fn test_example_case() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl Cursor<'_<|>> {
                fn node(self) -> &SyntaxNode {
                    match self {
                        Cursor::Replace(node) | Cursor::Before(node) => node,
                    }
                }
            }"#,
            r#"impl<'a> Cursor<'a> {
                fn node(self) -> &SyntaxNode {
                    match self {
                        Cursor::Replace(node) | Cursor::Before(node) => node,
                    }
                }
            }"#,
        );
    }

    #[test]
    fn test_example_case_simplified() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl Cursor<'_<|>> {"#,
            r#"impl<'a> Cursor<'a> {"#,
        );
    }

    #[test]
    fn test_not_applicable() {
        check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<'_><|> {"#);
        check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<|><'_> {"#);
        check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<'a<|>> {"#);
    }

    #[test]
    fn test_with_type_parameter() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl<T> Cursor<T, '_<|>>"#,
            r#"impl<T, 'a> Cursor<T, 'a>"#,
        );
    }
}
<commit_msg>handle the case of conflicting lifetime param name<commit_after>use crate::{AssistContext, AssistId, Assists};
use ra_syntax::{ast, ast::TypeParamsOwner, AstNode, SyntaxKind};
use std::collections::HashSet;

/// Assist: change_lifetime_anon_to_named
///
/// Change an anonymous lifetime to a named lifetime.
///
/// ```
/// impl Cursor<'_<|>> {
///     fn node(self) -> &SyntaxNode {
///         match self {
///             Cursor::Replace(node) | Cursor::Before(node) => node,
///         }
///     }
/// }
/// ```
/// ->
/// ```
/// impl<'a> Cursor<'a> {
///     fn node(self) -> &SyntaxNode {
///         match self {
///             Cursor::Replace(node) | Cursor::Before(node) => node,
///         }
///     }
/// }
/// ```
// FIXME: How can we handle renaming any one of multiple anonymous lifetimes?
pub(crate) fn change_lifetime_anon_to_named(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let lifetime_token = ctx.find_token_at_offset(SyntaxKind::LIFETIME)?;
    let lifetime_arg = ast::LifetimeArg::cast(lifetime_token.parent())?;
    if lifetime_arg.syntax().text() != "'_" {
        return None;
    }
    let next_token = lifetime_token.next_token()?;
    if next_token.kind() != SyntaxKind::R_ANGLE {
        // only allow naming the last anonymous lifetime
        return None;
    }
    match lifetime_arg.syntax().ancestors().find_map(ast::ImplDef::cast) {
        Some(impl_def) => {
            // get the `impl` keyword so we know where to add the lifetime argument
            let impl_kw = impl_def.syntax().first_child_or_token()?.into_token()?;
            if impl_kw.kind() != SyntaxKind::IMPL_KW {
                return None;
            }
            let new_lifetime_param = match impl_def.type_param_list() {
                Some(type_params) => {
                    let used_lifetime_params: HashSet<_> = type_params
                        .lifetime_params()
                        .map(|p| {
                            let mut param_name = p.syntax().text().to_string();
                            param_name.remove(0);
                            param_name
                        })
                        .collect();
                    "abcdefghijklmnopqrstuvwxyz"
                        .chars()
                        .find(|c| !used_lifetime_params.contains(&c.to_string()))?
                }
                None => 'a',
            };
            acc.add(
                AssistId("change_lifetime_anon_to_named"),
                "Give anonymous lifetime a name",
                lifetime_arg.syntax().text_range(),
                |builder| {
                    match impl_def.type_param_list() {
                        Some(type_params) => {
                            builder.insert(
                                (u32::from(type_params.syntax().text_range().end()) - 1).into(),
                                format!(", '{}", new_lifetime_param),
                            );
                        }
                        None => {
                            builder.insert(
                                impl_kw.text_range().end(),
                                format!("<'{}>", new_lifetime_param),
                            );
                        }
                    }
                    builder.replace(
                        lifetime_arg.syntax().text_range(),
                        format!("'{}", new_lifetime_param),
                    );
                },
            )
        }
        _ => None,
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::tests::{check_assist, check_assist_not_applicable};

    #[test]
    fn test_example_case() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl Cursor<'_<|>> {
                fn node(self) -> &SyntaxNode {
                    match self {
                        Cursor::Replace(node) | Cursor::Before(node) => node,
                    }
                }
            }"#,
            r#"impl<'a> Cursor<'a> {
                fn node(self) -> &SyntaxNode {
                    match self {
                        Cursor::Replace(node) | Cursor::Before(node) => node,
                    }
                }
            }"#,
        );
    }

    #[test]
    fn test_example_case_simplified() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl Cursor<'_<|>> {"#,
            r#"impl<'a> Cursor<'a> {"#,
        );
    }

    #[test]
    fn test_not_applicable() {
        check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<'_><|> {"#);
        check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<|><'_> {"#);
        check_assist_not_applicable(change_lifetime_anon_to_named, r#"impl Cursor<'a<|>> {"#);
    }

    #[test]
    fn test_with_type_parameter() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl<T> Cursor<T, '_<|>>"#,
            r#"impl<T, 'a> Cursor<T, 'a>"#,
        );
    }

    #[test]
    fn test_with_existing_lifetime_name_conflict() {
        check_assist(
            change_lifetime_anon_to_named,
            r#"impl<'a, 'b> Cursor<'a, 'b, '_<|>>"#,
            r#"impl<'a, 'b, 'c> Cursor<'a, 'b, 'c>"#,
        );
    }
}
<|endoftext|>


<commit_before>use epoch;

/// A guard used with epoch-based reclamation (EBR)
/// to track threads accessing shared lock-free
/// data structures, and safely drop data
/// after any thread may have accessed it.
pub type Guard = epoch::Guard;

/// Enter an epoch which allows us to safely
/// access shared data structures without
/// using mutexes.
pub fn pin() -> Guard {
    epoch::pin()
}

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully elliminated by the compiler in non-test code.
#[inline(always)]
pub fn debug_delay() {
    #[cfg(any(test, feature = "lock_free_delays"))]
    {
        use std::thread;
        use std::time::Duration;

        use rand::{
            distributions::{Distribution, Gamma},
            thread_rng, Rng,
        };

        if thread_rng().gen_bool(1. / 1000.) {
            let gamma = Gamma::new(0.3, 100000.0);
            let duration = gamma.sample(&mut thread_rng());
            thread::sleep(Duration::from_micros(duration as u64));
        }

        if thread_rng().gen::<bool>() {
            thread::yield_now();
        }
    }
}

pub(crate) fn u64_to_arr(u: u64) -> [u8; 8] {
    [
        u as u8,
        (u >> 8) as u8,
        (u >> 16) as u8,
        (u >> 24) as u8,
        (u >> 32) as u8,
        (u >> 40) as u8,
        (u >> 48) as u8,
        (u >> 56) as u8,
    ]
}

pub(crate) fn arr_to_u64(arr: [u8; 8]) -> u64 {
    arr[0] as u64
        + ((arr[1] as u64) << 8)
        + ((arr[2] as u64) << 16)
        + ((arr[3] as u64) << 24)
        + ((arr[4] as u64) << 32)
        + ((arr[5] as u64) << 40)
        + ((arr[6] as u64) << 48)
        + ((arr[7] as u64) << 56)
}

pub(crate) fn arr_to_u32(arr: [u8; 4]) -> u32 {
    arr[0] as u32
        + ((arr[1] as u32) << 8)
        + ((arr[2] as u32) << 16)
        + ((arr[3] as u32) << 24)
}

pub(crate) fn u32_to_arr(u: u32) -> [u8; 4] {
    [u as u8, (u >> 8) as u8, (u >> 16) as u8, (u >> 24) as u8]
}
<commit_msg>Add a spin_loop_hint into debug_delay<commit_after>use epoch;

/// A guard used with epoch-based reclamation (EBR)
/// to track threads accessing shared lock-free
/// data structures, and safely drop data
/// after any thread may have accessed it.
pub type Guard = epoch::Guard;

/// Enter an epoch which allows us to safely
/// access shared data structures without
/// using mutexes.
pub fn pin() -> Guard {
    epoch::pin()
}

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully elliminated by the compiler in non-test code.
#[inline(always)]
pub fn debug_delay() {
    #[cfg(any(test, feature = "lock_free_delays"))]
    {
        use std::sync::atomic::{spin_loop_hint, Ordering::SeqCst};
        use std::thread;
        use std::time::Duration;

        use rand::{
            distributions::{Distribution, Gamma},
            thread_rng, Rng,
        };

        if thread_rng().gen_bool(1. / 1000.) {
            let gamma = Gamma::new(0.3, 100000.0);
            let duration = gamma.sample(&mut thread_rng());
            thread::sleep(Duration::from_micros(duration as u64));
        }

        spin_loop_hint();

        if thread_rng().gen::<bool>() {
            thread::yield_now();
        }
    }
}

pub(crate) fn u64_to_arr(u: u64) -> [u8; 8] {
    [
        u as u8,
        (u >> 8) as u8,
        (u >> 16) as u8,
        (u >> 24) as u8,
        (u >> 32) as u8,
        (u >> 40) as u8,
        (u >> 48) as u8,
        (u >> 56) as u8,
    ]
}

pub(crate) fn arr_to_u64(arr: [u8; 8]) -> u64 {
    arr[0] as u64
        + ((arr[1] as u64) << 8)
        + ((arr[2] as u64) << 16)
        + ((arr[3] as u64) << 24)
        + ((arr[4] as u64) << 32)
        + ((arr[5] as u64) << 40)
        + ((arr[6] as u64) << 48)
        + ((arr[7] as u64) << 56)
}

pub(crate) fn arr_to_u32(arr: [u8; 4]) -> u32 {
    arr[0] as u32
        + ((arr[1] as u32) << 8)
        + ((arr[2] as u32) << 16)
        + ((arr[3] as u32) << 24)
}

pub(crate) fn u32_to_arr(u: u32) -> [u8; 4] {
    [u as u8, (u >> 8) as u8, (u >> 16) as u8, (u >> 24) as u8]
}
<|endoftext|>


<commit_before>//! This module contains utilities for turning SyntaxNodes and HIR types
//! into types that may be used to render in a UI.

mod function_signature;
mod navigation_target;
mod structure;
mod short_label;

use std::fmt::Display;

use ra_syntax::{
    ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner},
    SyntaxKind::{ATTR, COMMENT},
};
use stdx::format_to;

pub use function_signature::FunctionSignature;
pub use navigation_target::NavigationTarget;
pub use structure::{file_structure, StructureNode};

pub(crate) use navigation_target::{ToNav, TryToNav};
pub(crate) use short_label::ShortLabel;

pub(crate) fn function_label(node: &ast::FnDef) -> String {
    FunctionSignature::from(node).to_string()
}

pub(crate) fn const_label(node: &ast::ConstDef) -> String {
    let label: String = node
        .syntax()
        .children_with_tokens()
        .filter(|child| !(child.kind() == COMMENT || child.kind() == ATTR))
        .map(|node| node.to_string())
        .collect();

    label.trim().to_owned()
}

pub(crate) fn type_label(node: &ast::TypeAliasDef) -> String {
    let label: String = node
        .syntax()
        .children_with_tokens()
        .filter(|child| !(child.kind() == COMMENT || child.kind() == ATTR))
        .map(|node| node.to_string())
        .collect();

    label.trim().to_owned()
}

pub(crate) fn generic_parameters<N: TypeParamsOwner>(node: &N) -> Vec<String> {
    let mut res = vec![];
    if let Some(type_params) = node.type_param_list() {
        res.extend(type_params.lifetime_params().map(|p| p.syntax().text().to_string()));
        res.extend(type_params.type_params().map(|p| p.syntax().text().to_string()));
    }
    res
}

pub(crate) fn where_predicates<N: TypeParamsOwner>(node: &N) -> Vec<String> {
    let mut res = vec![];
    if let Some(clause) = node.where_clause() {
        res.extend(clause.predicates().map(|p| p.syntax().text().to_string()));
    }
    res
}

pub(crate) fn macro_label(node: &ast::MacroCall) -> String {
    let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default();
    let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" };
    format!("{}macro_rules! {}", vis, name)
}

pub(crate) fn rust_code_markup(code: &impl Display) -> String {
    rust_code_markup_with_doc(code, None, None)
}

pub(crate) fn rust_code_markup_with_doc(
    code: &impl Display,
    doc: Option<&str>,
    mod_path: Option<&str>,
) -> String {
    let mut buf = "```rust\n".to_owned();

    if let Some(mod_path) = mod_path {
        if !mod_path.is_empty() {
            format_to!(buf, "{}\n", mod_path);
        }
    }
    format_to!(buf, "{}\n```", code);

    if let Some(doc) = doc {
        format_to!(buf, "\n\n{}", doc);
    }

    buf
}
<commit_msg>Add extra newline after module path in hover info<commit_after>//! This module contains utilities for turning SyntaxNodes and HIR types
//! into types that may be used to render in a UI.

mod function_signature;
mod navigation_target;
mod structure;
mod short_label;

use std::fmt::Display;

use ra_syntax::{
    ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner},
    SyntaxKind::{ATTR, COMMENT},
};
use stdx::format_to;

pub use function_signature::FunctionSignature;
pub use navigation_target::NavigationTarget;
pub use structure::{file_structure, StructureNode};

pub(crate) use navigation_target::{ToNav, TryToNav};
pub(crate) use short_label::ShortLabel;

pub(crate) fn function_label(node: &ast::FnDef) -> String {
    FunctionSignature::from(node).to_string()
}

pub(crate) fn const_label(node: &ast::ConstDef) -> String {
    let label: String = node
        .syntax()
        .children_with_tokens()
        .filter(|child| !(child.kind() == COMMENT || child.kind() == ATTR))
        .map(|node| node.to_string())
        .collect();

    label.trim().to_owned()
}

pub(crate) fn type_label(node: &ast::TypeAliasDef) -> String {
    let label: String = node
        .syntax()
        .children_with_tokens()
        .filter(|child| !(child.kind() == COMMENT || child.kind() == ATTR))
        .map(|node| node.to_string())
        .collect();

    label.trim().to_owned()
}

pub(crate) fn generic_parameters<N: TypeParamsOwner>(node: &N) -> Vec<String> {
    let mut res = vec![];
    if let Some(type_params) = node.type_param_list() {
        res.extend(type_params.lifetime_params().map(|p| p.syntax().text().to_string()));
        res.extend(type_params.type_params().map(|p| p.syntax().text().to_string()));
    }
    res
}

pub(crate) fn where_predicates<N: TypeParamsOwner>(node: &N) -> Vec<String> {
    let mut res = vec![];
    if let Some(clause) = node.where_clause() {
        res.extend(clause.predicates().map(|p| p.syntax().text().to_string()));
    }
    res
}

pub(crate) fn macro_label(node: &ast::MacroCall) -> String {
    let name = node.name().map(|name| name.syntax().text().to_string()).unwrap_or_default();
    let vis = if node.has_atom_attr("macro_export") { "#[macro_export]\n" } else { "" };
    format!("{}macro_rules! {}", vis, name)
}

pub(crate) fn rust_code_markup(code: &impl Display) -> String {
    rust_code_markup_with_doc(code, None, None)
}

pub(crate) fn rust_code_markup_with_doc(
    code: &impl Display,
    doc: Option<&str>,
    mod_path: Option<&str>,
) -> String {
    let mut buf = "```rust\n".to_owned();

    if let Some(mod_path) = mod_path {
        if !mod_path.is_empty() {
            format_to!(buf, "{}\n\n", mod_path);
        }
    }
    format_to!(buf, "{}\n```", code);

    if let Some(doc) = doc {
        format_to!(buf, "\n\n{}", doc);
    }

    buf
}
<|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/.

extern crate devicemapper;
extern crate libstratis;
extern crate rand;
extern crate tempdir;
extern crate time;
extern crate uuid;

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

use self::devicemapper::DM;
use self::devicemapper::consts::SECTOR_SIZE;
use self::devicemapper::LinearDev;
use self::devicemapper::Segment;
use self::devicemapper::{DataBlocks, Sectors};
use self::devicemapper::ThinDev;
use self::devicemapper::ThinPoolDev;

use self::tempdir::TempDir;
use self::uuid::Uuid;

use libstratis::engine::{Engine, EngineError, ErrorEnum};
use libstratis::engine::strat_engine::StratEngine;
use libstratis::engine::strat_engine::blockdevmgr::{initialize, resolve_devices};
use libstratis::engine::strat_engine::device::{blkdev_size, write_sectors};
use libstratis::engine::strat_engine::engine::DevOwnership;
use libstratis::engine::strat_engine::filesystem::{create_fs, mount_fs, unmount_fs};
use libstratis::engine::strat_engine::metadata::{StaticHeader, BDA_STATIC_HDR_SECTORS,
                                                 MIN_MDA_SECTORS};
use libstratis::engine::strat_engine::setup::{find_all, get_pool_metadata};

/// Dirty sectors where specified, with 1s.
fn dirty_sectors(path: &Path, offset: Sectors, length: Sectors) {
    write_sectors(path, offset, length, &[1u8; SECTOR_SIZE]).unwrap();
}

/// Verify that it is impossible to initialize a set of disks of which
/// even one is dirty, i.e, has some data written within BDA_STATIC_HDR_SECTORS
/// of start of disk. Choose the dirty disk randomly. This means that even
/// if our code is broken with respect to this property, this test might
/// sometimes succeed.
/// FIXME: Consider enriching device specs so that this test will fail
/// consistently.
/// Verify that force flag allows all dirty disks to be initialized.
pub fn test_force_flag_dirty(paths: &[&Path]) -> () {

    let index = rand::random::<u8>() as usize % paths.len();
    dirty_sectors(paths[index],
                  Sectors(index as u64 % *BDA_STATIC_HDR_SECTORS),
                  Sectors(1));

    let unique_devices = resolve_devices(&paths).unwrap();

    let uuid = Uuid::new_v4();
    assert!(initialize(&uuid, unique_devices.clone(), MIN_MDA_SECTORS, false).is_err());
    assert!(paths
                .iter()
                .enumerate()
                .all(|(i, path)| {
        StaticHeader::determine_ownership(&mut OpenOptions::new().read(true).open(path).unwrap())
            .unwrap() ==
        if i == index {
            DevOwnership::Theirs
        } else {
            DevOwnership::Unowned
        }
    }));

    assert!(initialize(&uuid, unique_devices.clone(), MIN_MDA_SECTORS, true).is_ok());
    assert!(paths
                .iter()
                .all(|path| {
                         StaticHeader::determine_ownership(&mut OpenOptions::new()
                                                                    .read(true)
                                                                    .open(path)
                                                                    .unwrap())
                                 .unwrap() == DevOwnership::Ours(uuid)
                     }));
}

/// Verify that it is impossible to steal blockdevs from another Stratis
/// pool.
/// 1. Initialize devices with pool uuid.
/// 2. Initializing again with different uuid must fail.
/// 3. Initializing again with same pool uuid must succeed, because all the
/// devices already belong so there's nothing to do.
/// 4. Initializing again with different uuid and force = true also fails.
pub fn test_force_flag_stratis(paths: &[&Path]) -> () {
    let unique_devices = resolve_devices(&paths).unwrap();

    let uuid = Uuid::new_v4();
    let uuid2 = Uuid::new_v4();

    initialize(&uuid, unique_devices.clone(), MIN_MDA_SECTORS, false).unwrap();
    assert!(initialize(&uuid2, unique_devices.clone(), MIN_MDA_SECTORS, false).is_err());

    assert!(initialize(&uuid, unique_devices.clone(), MIN_MDA_SECTORS, false).is_ok());

    // FIXME: this should succeed, but currently it fails, to be extra safe.
    // See: https://github.com/stratis-storage/stratisd/pull/292
    assert!(initialize(&uuid2, unique_devices.clone(), MIN_MDA_SECTORS, true).is_err());
}

/// Verify that the sum of the lengths of the available range of the
/// blockdevs in the linear device equals the size of the linear device.
pub fn test_linear_device(paths: &[&Path]) -> () {
    let unique_devices = resolve_devices(&paths).unwrap();
    let initialized = initialize(&Uuid::new_v4(),
                                 unique_devices.clone(),
                                 MIN_MDA_SECTORS,
                                 false)
            .unwrap();
    let total_blockdev_size = initialized
        .iter()
        .fold(Sectors(0), |s, i| s + i.avail_range().length);

    let segments = initialized
        .iter()
        .map(|block_dev| block_dev.avail_range())
        .collect::<Vec<Segment>>();

    let device_name = "stratis_testing_linear";
    let dm = DM::new().unwrap();
    let lineardev = LinearDev::new(&device_name, &dm, segments).unwrap();

    let mut linear_dev_path = PathBuf::from("/dev/mapper");
    linear_dev_path.push(device_name);

    let lineardev_size = blkdev_size(&File::open(linear_dev_path).unwrap()).unwrap();
    assert!(total_blockdev_size.bytes() == lineardev_size);
    lineardev.teardown(&dm).unwrap();
}

/// Verify no errors when writing files to a mounted filesystem on a thin
/// device.
pub fn test_thinpool_device(paths: &[&Path]) -> () {
    let initialized = initialize(&Uuid::new_v4(),
                                 resolve_devices(&paths).unwrap(),
                                 MIN_MDA_SECTORS,
                                 false)
            .unwrap();

    let (metadata_blockdev, data_blockdev) = (initialized.first().unwrap(),
                                              initialized.last().unwrap());

    let dm = DM::new().unwrap();
    let metadata_dev = LinearDev::new("stratis_testing_thinpool_metadata",
                                      &dm,
                                      vec![metadata_blockdev.avail_range()])
            .unwrap();
    let data_dev = LinearDev::new("stratis_testing_thinpool_datadev",
                                  &dm,
                                  vec![data_blockdev.avail_range()])
            .unwrap();
    let thinpool_dev = ThinPoolDev::new("stratis_testing_thinpool",
                                        &dm,
                                        data_dev.size().unwrap(),
                                        Sectors(1024),
                                        DataBlocks(256000),
                                        metadata_dev,
                                        data_dev)
            .unwrap();
    let thin_dev = ThinDev::new("stratis_testing_thindev",
                                &dm,
                                &thinpool_dev,
                                7,
                                Sectors(300000))
            .unwrap();

    create_fs(&thin_dev.devnode().unwrap()).unwrap();

    let tmp_dir = TempDir::new("stratis_testing").unwrap();
    mount_fs(&thin_dev.devnode().unwrap(), tmp_dir.path()).unwrap();
    unmount_fs(tmp_dir.path()).unwrap();
    for i in 0..100 {
        let file_path = tmp_dir.path().join(format!("stratis_test{}.txt", i));
        writeln!(&File::create(file_path).unwrap(), "data").unwrap();
    }
    thin_dev.teardown(&dm).unwrap();
    thinpool_dev.teardown(&dm).unwrap();
}

/// Test that creating a pool claims all blockdevs and that destroying a pool
/// releases all blockdevs.
pub fn test_pool_blockdevs(paths: &[&Path]) -> () {
    let mut engine = StratEngine::initialize().unwrap();
    let (uuid, blockdevs) = engine
        .create_pool("test_pool", paths, None, true)
        .unwrap();
    assert!(blockdevs
                .iter()
                .all(|path| {
                         StaticHeader::determine_ownership(&mut OpenOptions::new()
                                                                    .read(true)
                                                                    .open(path)
                                                                    .unwrap())
                                 .unwrap() == DevOwnership::Ours(uuid)
                     }));
    engine.destroy_pool(&uuid).unwrap();
    assert!(blockdevs
                .iter()
                .all(|path| {
                         StaticHeader::determine_ownership(&mut OpenOptions::new()
                                                                    .read(true)
                                                                    .open(path)
                                                                    .unwrap())
                                 .unwrap() == DevOwnership::Unowned
                     }));
}

/// Verify that tearing down an engine doesn't fail if no filesystems on it.
pub fn test_teardown(paths: &[&Path]) -> () {
    let mut engine = StratEngine::initialize().unwrap();
    engine
        .create_pool("test_pool", paths, None, true)
        .unwrap();
    assert!(engine.teardown().is_ok())
}

/// Verify that find_all function locates and assigns pools appropriately.
/// 1. Split available paths into 2 discrete sets.
/// 2. Initialize the block devices in the first set with a pool uuid.
/// 3. Run find_all() and verify that it has found the initialized devices
/// and no others.
/// 4. Initialize the block devices in the second set with a different pool
/// uuid.
/// 5. Run find_all() again and verify that both sets of devices are found.
/// 6. Verify that get_pool_metadata() return an error. initialize() only
/// initializes block devices, it does not write metadata.
pub fn test_setup(paths: &[&Path]) -> () {
    assert!(paths.len() > 2);

    let (paths1, paths2) = paths.split_at(2);

    let unique_devices = resolve_devices(paths1).unwrap();
    let uuid1 = Uuid::new_v4();
    initialize(&uuid1, unique_devices, MIN_MDA_SECTORS, false).unwrap();

    let pools = find_all().unwrap();
    assert!(pools.len() == 1);
    assert!(pools.contains_key(&uuid1));
    let devices = pools.get(&uuid1).expect("pools.contains_key() was true");
    assert!(devices.len() == paths1.len());

    let unique_devices = resolve_devices(paths2).unwrap();
    let uuid2 = Uuid::new_v4();
    initialize(&uuid2, unique_devices, MIN_MDA_SECTORS, false).unwrap();

    let pools = find_all().unwrap();
    assert!(pools.len() == 2);

    assert!(pools.contains_key(&uuid1));
    let devices1 = pools.get(&uuid1).expect("pools.contains_key() was true");
    assert!(devices1.len() == paths1.len());

    assert!(pools.contains_key(&uuid2));
    let devices2 = pools.get(&uuid2).expect("pools.contains_key() was true");
    assert!(devices2.len() == paths2.len());

    assert!(get_pool_metadata(&pools).is_err());
}

/// Verify that a pool with no devices does not have the minimum amount of
/// space required.
pub fn test_empty_pool(paths: &[&Path]) -> () {
    assert!(paths.len() == 0);
    let mut engine = StratEngine::initialize().unwrap();
    assert!(match engine
                      .create_pool("test_pool", paths, None, true)
                      .unwrap_err() {
                EngineError::Engine(ErrorEnum::Invalid, _) => true,
                _ => false,
            });
}

/// Verify that metadata can be read from pools.
/// 1. Split paths into two separate sets.
/// 2. Create a pool from the first set.
/// 3. Use find_all() to get the devices in the pool.
/// 4. Use get_pool_metadata to find metadata for all pools.
/// 5. Verify that metadata name is correct.
/// 6. Create a second pool and repeat.
/// 7. Teardown the engine and repeat.
pub fn test_basic_metadata(paths: &[&Path]) {
    assert!(paths.len() > 2);

    let (paths1, paths2) = paths.split_at(2);

    let mut engine = StratEngine::initialize().unwrap();

    let name1 = "name1";
    let (uuid1, _) = engine.create_pool(&name1, paths1, None, false).unwrap();

    let pools = find_all().unwrap();
    let metadata = get_pool_metadata(&pools).unwrap();
    assert!(metadata.len() == 1);
    assert!(metadata.get(&uuid1).unwrap().name == name1);

    let name2 = "name2";
    let (uuid2, _) = engine.create_pool(&name2, paths2, None, false).unwrap();

    let pools = find_all().unwrap();
    let metadata = get_pool_metadata(&pools).unwrap();
    assert!(metadata.len() == 2);
    assert!(metadata.get(&uuid1).unwrap().name == name1);
    assert!(metadata.get(&uuid2).unwrap().name == name2);

    engine.teardown().unwrap();
    let pools = find_all().unwrap();
    let metadata = get_pool_metadata(&pools).unwrap();
    assert!(metadata.len() == 2);
    assert!(metadata.get(&uuid1).unwrap().name == name1);
    assert!(metadata.get(&uuid2).unwrap().name == name2);
}
<commit_msg>Substitute OpenOptions for File in all calls<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/.

extern crate devicemapper;
extern crate libstratis;
extern crate rand;
extern crate tempdir;
extern crate time;
extern crate uuid;

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

use self::devicemapper::DM;
use self::devicemapper::consts::SECTOR_SIZE;
use self::devicemapper::LinearDev;
use self::devicemapper::Segment;
use self::devicemapper::{DataBlocks, Sectors};
use self::devicemapper::ThinDev;
use self::devicemapper::ThinPoolDev;

use self::tempdir::TempDir;
use self::uuid::Uuid;

use libstratis::engine::{Engine, EngineError, ErrorEnum};
use libstratis::engine::strat_engine::StratEngine;
use libstratis::engine::strat_engine::blockdevmgr::{initialize, resolve_devices};
use libstratis::engine::strat_engine::device::{blkdev_size, write_sectors};
use libstratis::engine::strat_engine::engine::DevOwnership;
use libstratis::engine::strat_engine::filesystem::{create_fs, mount_fs, unmount_fs};
use libstratis::engine::strat_engine::metadata::{StaticHeader, BDA_STATIC_HDR_SECTORS,
                                                 MIN_MDA_SECTORS};
use libstratis::engine::strat_engine::setup::{find_all, get_pool_metadata};

/// Dirty sectors where specified, with 1s.
fn dirty_sectors(path: &Path, offset: Sectors, length: Sectors) {
    write_sectors(path, offset, length, &[1u8; SECTOR_SIZE]).unwrap();
}

/// Verify that it is impossible to initialize a set of disks of which
/// even one is dirty, i.e, has some data written within BDA_STATIC_HDR_SECTORS
/// of start of disk. Choose the dirty disk randomly. This means that even
/// if our code is broken with respect to this property, this test might
/// sometimes succeed.
/// FIXME: Consider enriching device specs so that this test will fail
/// consistently.
/// Verify that force flag allows all dirty disks to be initialized.
pub fn test_force_flag_dirty(paths: &[&Path]) -> () {

    let index = rand::random::<u8>() as usize % paths.len();
    dirty_sectors(paths[index],
                  Sectors(index as u64 % *BDA_STATIC_HDR_SECTORS),
                  Sectors(1));

    let unique_devices = resolve_devices(&paths).unwrap();

    let uuid = Uuid::new_v4();
    assert!(initialize(&uuid, unique_devices.clone(), MIN_MDA_SECTORS, false).is_err());
    assert!(paths
                .iter()
                .enumerate()
                .all(|(i, path)| {
        StaticHeader::determine_ownership(&mut OpenOptions::new().read(true).open(path).unwrap())
            .unwrap() ==
        if i == index {
            DevOwnership::Theirs
        } else {
            DevOwnership::Unowned
        }
    }));

    assert!(initialize(&uuid, unique_devices.clone(), MIN_MDA_SECTORS, true).is_ok());
    assert!(paths
                .iter()
                .all(|path| {
                         StaticHeader::determine_ownership(&mut OpenOptions::new()
                                                                    .read(true)
                                                                    .open(path)
                                                                    .unwrap())
                                 .unwrap() == DevOwnership::Ours(uuid)
                     }));
}

/// Verify that it is impossible to steal blockdevs from another Stratis
/// pool.
/// 1. Initialize devices with pool uuid.
/// 2. Initializing again with different uuid must fail.
/// 3. Initializing again with same pool uuid must succeed, because all the
/// devices already belong so there's nothing to do.
/// 4. Initializing again with different uuid and force = true also fails.
pub fn test_force_flag_stratis(paths: &[&Path]) -> () {
    let unique_devices = resolve_devices(&paths).unwrap();

    let uuid = Uuid::new_v4();
    let uuid2 = Uuid::new_v4();

    initialize(&uuid, unique_devices.clone(), MIN_MDA_SECTORS, false).unwrap();
    assert!(initialize(&uuid2, unique_devices.clone(), MIN_MDA_SECTORS, false).is_err());

    assert!(initialize(&uuid, unique_devices.clone(), MIN_MDA_SECTORS, false).is_ok());

    // FIXME: this should succeed, but currently it fails, to be extra safe.
    // See: https://github.com/stratis-storage/stratisd/pull/292
    assert!(initialize(&uuid2, unique_devices.clone(), MIN_MDA_SECTORS, true).is_err());
}

/// Verify that the sum of the lengths of the available range of the
/// blockdevs in the linear device equals the size of the linear device.
pub fn test_linear_device(paths: &[&Path]) -> () {
    let unique_devices = resolve_devices(&paths).unwrap();
    let initialized = initialize(&Uuid::new_v4(),
                                 unique_devices.clone(),
                                 MIN_MDA_SECTORS,
                                 false)
            .unwrap();
    let total_blockdev_size = initialized
        .iter()
        .fold(Sectors(0), |s, i| s + i.avail_range().length);

    let segments = initialized
        .iter()
        .map(|block_dev| block_dev.avail_range())
        .collect::<Vec<Segment>>();

    let device_name = "stratis_testing_linear";
    let dm = DM::new().unwrap();
    let lineardev = LinearDev::new(&device_name, &dm, segments).unwrap();

    let mut linear_dev_path = PathBuf::from("/dev/mapper");
    linear_dev_path.push(device_name);

    let lineardev_size = blkdev_size(&OpenOptions::new()
                                          .read(true)
                                          .open(linear_dev_path)
                                          .unwrap())
            .unwrap();
    assert!(total_blockdev_size.bytes() == lineardev_size);
    lineardev.teardown(&dm).unwrap();
}

/// Verify no errors when writing files to a mounted filesystem on a thin
/// device.
pub fn test_thinpool_device(paths: &[&Path]) -> () {
    let initialized = initialize(&Uuid::new_v4(),
                                 resolve_devices(&paths).unwrap(),
                                 MIN_MDA_SECTORS,
                                 false)
            .unwrap();

    let (metadata_blockdev, data_blockdev) = (initialized.first().unwrap(),
                                              initialized.last().unwrap());

    let dm = DM::new().unwrap();
    let metadata_dev = LinearDev::new("stratis_testing_thinpool_metadata",
                                      &dm,
                                      vec![metadata_blockdev.avail_range()])
            .unwrap();
    let data_dev = LinearDev::new("stratis_testing_thinpool_datadev",
                                  &dm,
                                  vec![data_blockdev.avail_range()])
            .unwrap();
    let thinpool_dev = ThinPoolDev::new("stratis_testing_thinpool",
                                        &dm,
                                        data_dev.size().unwrap(),
                                        Sectors(1024),
                                        DataBlocks(256000),
                                        metadata_dev,
                                        data_dev)
            .unwrap();
    let thin_dev = ThinDev::new("stratis_testing_thindev",
                                &dm,
                                &thinpool_dev,
                                7,
                                Sectors(300000))
            .unwrap();

    create_fs(&thin_dev.devnode().unwrap()).unwrap();

    let tmp_dir = TempDir::new("stratis_testing").unwrap();
    mount_fs(&thin_dev.devnode().unwrap(), tmp_dir.path()).unwrap();
    unmount_fs(tmp_dir.path()).unwrap();
    for i in 0..100 {
        let file_path = tmp_dir.path().join(format!("stratis_test{}.txt", i));
        writeln!(&OpenOptions::new()
                      .create(true)
                      .write(true)
                      .open(file_path)
                      .unwrap(),
                 "data")
                .unwrap();
    }
    thin_dev.teardown(&dm).unwrap();
    thinpool_dev.teardown(&dm).unwrap();
}

/// Test that creating a pool claims all blockdevs and that destroying a pool
/// releases all blockdevs.
pub fn test_pool_blockdevs(paths: &[&Path]) -> () {
    let mut engine = StratEngine::initialize().unwrap();
    let (uuid, blockdevs) = engine
        .create_pool("test_pool", paths, None, true)
        .unwrap();
    assert!(blockdevs
                .iter()
                .all(|path| {
                         StaticHeader::determine_ownership(&mut OpenOptions::new()
                                                                    .read(true)
                                                                    .open(path)
                                                                    .unwrap())
                                 .unwrap() == DevOwnership::Ours(uuid)
                     }));
    engine.destroy_pool(&uuid).unwrap();
    assert!(blockdevs
                .iter()
                .all(|path| {
                         StaticHeader::determine_ownership(&mut OpenOptions::new()
                                                                    .read(true)
                                                                    .open(path)
                                                                    .unwrap())
                                 .unwrap() == DevOwnership::Unowned
                     }));
}

/// Verify that tearing down an engine doesn't fail if no filesystems on it.
pub fn test_teardown(paths: &[&Path]) -> () {
    let mut engine = StratEngine::initialize().unwrap();
    engine
        .create_pool("test_pool", paths, None, true)
        .unwrap();
    assert!(engine.teardown().is_ok())
}

/// Verify that find_all function locates and assigns pools appropriately.
/// 1. Split available paths into 2 discrete sets.
/// 2. Initialize the block devices in the first set with a pool uuid.
/// 3. Run find_all() and verify that it has found the initialized devices
/// and no others.
/// 4. Initialize the block devices in the second set with a different pool
/// uuid.
/// 5. Run find_all() again and verify that both sets of devices are found.
/// 6. Verify that get_pool_metadata() return an error. initialize() only
/// initializes block devices, it does not write metadata.
pub fn test_setup(paths: &[&Path]) -> () {
    assert!(paths.len() > 2);

    let (paths1, paths2) = paths.split_at(2);

    let unique_devices = resolve_devices(paths1).unwrap();
    let uuid1 = Uuid::new_v4();
    initialize(&uuid1, unique_devices, MIN_MDA_SECTORS, false).unwrap();

    let pools = find_all().unwrap();
    assert!(pools.len() == 1);
    assert!(pools.contains_key(&uuid1));
    let devices = pools.get(&uuid1).expect("pools.contains_key() was true");
    assert!(devices.len() == paths1.len());

    let unique_devices = resolve_devices(paths2).unwrap();
    let uuid2 = Uuid::new_v4();
    initialize(&uuid2, unique_devices, MIN_MDA_SECTORS, false).unwrap();

    let pools = find_all().unwrap();
    assert!(pools.len() == 2);

    assert!(pools.contains_key(&uuid1));
    let devices1 = pools.get(&uuid1).expect("pools.contains_key() was true");
    assert!(devices1.len() == paths1.len());

    assert!(pools.contains_key(&uuid2));
    let devices2 = pools.get(&uuid2).expect("pools.contains_key() was true");
    assert!(devices2.len() == paths2.len());

    assert!(get_pool_metadata(&pools).is_err());
}

/// Verify that a pool with no devices does not have the minimum amount of
/// space required.
pub fn test_empty_pool(paths: &[&Path]) -> () {
    assert!(paths.len() == 0);
    let mut engine = StratEngine::initialize().unwrap();
    assert!(match engine
                      .create_pool("test_pool", paths, None, true)
                      .unwrap_err() {
                EngineError::Engine(ErrorEnum::Invalid, _) => true,
                _ => false,
            });
}

/// Verify that metadata can be read from pools.
/// 1. Split paths into two separate sets.
/// 2. Create a pool from the first set.
/// 3. Use find_all() to get the devices in the pool.
/// 4. Use get_pool_metadata to find metadata for all pools.
/// 5. Verify that metadata name is correct.
/// 6. Create a second pool and repeat.
/// 7. Teardown the engine and repeat.
pub fn test_basic_metadata(paths: &[&Path]) {
    assert!(paths.len() > 2);

    let (paths1, paths2) = paths.split_at(2);

    let mut engine = StratEngine::initialize().unwrap();

    let name1 = "name1";
    let (uuid1, _) = engine.create_pool(&name1, paths1, None, false).unwrap();

    let pools = find_all().unwrap();
    let metadata = get_pool_metadata(&pools).unwrap();
    assert!(metadata.len() == 1);
    assert!(metadata.get(&uuid1).unwrap().name == name1);

    let name2 = "name2";
    let (uuid2, _) = engine.create_pool(&name2, paths2, None, false).unwrap();

    let pools = find_all().unwrap();
    let metadata = get_pool_metadata(&pools).unwrap();
    assert!(metadata.len() == 2);
    assert!(metadata.get(&uuid1).unwrap().name == name1);
    assert!(metadata.get(&uuid2).unwrap().name == name2);

    engine.teardown().unwrap();
    let pools = find_all().unwrap();
    let metadata = get_pool_metadata(&pools).unwrap();
    assert!(metadata.len() == 2);
    assert!(metadata.get(&uuid1).unwrap().name == name1);
    assert!(metadata.get(&uuid2).unwrap().name == name2);
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::net::{TcpListener, SocketAddr, TcpStream};
use std::io::prelude::*;
use std::thread;
use std::sync::mpsc::{Sender, Receiver, channel};
use std::io::BufReader;

pub struct Server {
    messages: Option<Sender<Message>>,
    addr: SocketAddr,
    thread: Option<thread::JoinHandle<()>>,
}

enum Message {
    Read(String),
    Write(String),
}

fn run(listener: &TcpListener, rx: &Receiver<Message>) {
    let mut socket = BufReader::new(listener.accept().unwrap().0);
    for msg in rx.iter() {
        match msg {
            Message::Read(ref expected) => {
                let mut expected = &expected[..];
                let mut expected_headers = HashSet::new();
                while let Some(i) = expected.find("\n") {
                    let line = &expected[..i + 1];
                    expected = &expected[i + 1..];
                    if line == "\r" || line == "" {
                        break
                    }
                    expected_headers.insert(line);
                }
                if expected.len() > 0 {
                    assert!(expected_headers.insert(expected));
                }

                while expected_headers.len() > 0 {
                    let mut actual = String::new();
                    t!(socket.read_line(&mut actual));
                    if !expected_headers.remove(&actual[..]) {
                        panic!("unexpected header: {:?}", actual);
                    }
                }
                for header in expected_headers {
                    panic!("expected header but not found: {:?}", header);
                }

                let mut buf = vec![0; expected.len()];
                if buf.len() > 0 {
                    t!(socket.read_exact(&mut buf));
                    assert_eq!(buf, expected.as_bytes());
                }
            }
            Message::Write(ref to_write) => {
                t!(socket.get_mut().write_all(to_write.as_bytes()));
                return
            }
        }
    }

    let mut dst = Vec::new();
    t!(socket.read_to_end(&mut dst));
    assert!(dst.len() == 0);
}

impl Server {
    pub fn new() -> Server {
        let listener = t!(TcpListener::bind("127.0.0.1:0"));
        let addr = t!(listener.local_addr());
        let (tx, rx) = channel();
        let thread = thread::spawn(move || run(&listener, &rx));
        Server {
            messages: Some(tx),
            addr: addr,
            thread: Some(thread),
        }
    }

    pub fn receive(&self, msg: &str) {
        let msg = msg.replace("$PORT", &self.addr.port().to_string());
        self.msg(Message::Read(msg));
    }

    pub fn send(&self, msg: &str) {
        let msg = msg.replace("$PORT", &self.addr.port().to_string());
        self.msg(Message::Write(msg));
    }

    fn msg(&self, msg: Message) {
        t!(self.messages.as_ref().unwrap().send(msg));
    }

    pub fn addr(&self) -> &SocketAddr {
        &self.addr
    }

    pub fn url(&self, path: &str) -> String {
        format!("http://{}{}", self.addr, path)
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        drop(TcpStream::connect(&self.addr));
        drop(self.messages.take());
        let res = self.thread.take().unwrap().join();
        if !thread::panicking() {
            t!(res);
        } else if let Err(e) = res {
            println!("child server thread also failed: {:?}", e);
        }
    }
}
<commit_msg>Help debug test failures<commit_after>use std::collections::HashSet;
use std::net::{TcpListener, SocketAddr, TcpStream};
use std::io::prelude::*;
use std::thread;
use std::sync::mpsc::{Sender, Receiver, channel};
use std::io::BufReader;

pub struct Server {
    messages: Option<Sender<Message>>,
    addr: SocketAddr,
    thread: Option<thread::JoinHandle<()>>,
}

enum Message {
    Read(String),
    Write(String),
}

fn run(listener: &TcpListener, rx: &Receiver<Message>) {
    let mut socket = BufReader::new(listener.accept().unwrap().0);
    for msg in rx.iter() {
        match msg {
            Message::Read(ref expected) => {
                let mut expected = &expected[..];
                let mut expected_headers = HashSet::new();
                while let Some(i) = expected.find("\n") {
                    let line = &expected[..i + 1];
                    expected = &expected[i + 1..];
                    if line == "\r" || line == "" {
                        break
                    }
                    expected_headers.insert(line);
                }
                if expected.len() > 0 {
                    assert!(expected_headers.insert(expected));
                }

                while expected_headers.len() > 0 {
                    let mut actual = String::new();
                    t!(socket.read_line(&mut actual));
                    if !expected_headers.remove(&actual[..]) {
                        panic!("unexpected header: {:?} (remaining headers {:?})",
                               actual, expected_headers);
                    }
                }
                for header in expected_headers {
                    panic!("expected header but not found: {:?}", header);
                }

                let mut buf = vec![0; expected.len()];
                if buf.len() > 0 {
                    t!(socket.read_exact(&mut buf));
                    assert_eq!(buf, expected.as_bytes());
                }
            }
            Message::Write(ref to_write) => {
                t!(socket.get_mut().write_all(to_write.as_bytes()));
                return
            }
        }
    }

    let mut dst = Vec::new();
    t!(socket.read_to_end(&mut dst));
    assert!(dst.len() == 0);
}

impl Server {
    pub fn new() -> Server {
        let listener = t!(TcpListener::bind("127.0.0.1:0"));
        let addr = t!(listener.local_addr());
        let (tx, rx) = channel();
        let thread = thread::spawn(move || run(&listener, &rx));
        Server {
            messages: Some(tx),
            addr: addr,
            thread: Some(thread),
        }
    }

    pub fn receive(&self, msg: &str) {
        let msg = msg.replace("$PORT", &self.addr.port().to_string());
        self.msg(Message::Read(msg));
    }

    pub fn send(&self, msg: &str) {
        let msg = msg.replace("$PORT", &self.addr.port().to_string());
        self.msg(Message::Write(msg));
    }

    fn msg(&self, msg: Message) {
        t!(self.messages.as_ref().unwrap().send(msg));
    }

    pub fn addr(&self) -> &SocketAddr {
        &self.addr
    }

    pub fn url(&self, path: &str) -> String {
        format!("http://{}{}", self.addr, path)
    }
}

impl Drop for Server {
    fn drop(&mut self) {
        drop(TcpStream::connect(&self.addr));
        drop(self.messages.take());
        let res = self.thread.take().unwrap().join();
        if !thread::panicking() {
            t!(res);
        } else if let Err(e) = res {
            println!("child server thread also failed: {:?}", e);
        }
    }
}
<|endoftext|>


<commit_before>#![crate_name = "orbtk"]
#![crate_type = "lib"]

//! # OrbTK - The Orbital Toolkit
//!
//! ![Welcome to the OrbTk planet.][orbtk_planet]
//!
//! The `OrbTK` crate implements a cross-platform (G)UI toolkit for
//! building scalable user interfaces. The codebase is natively build
//! with the `Rust` programming language.
//!
//! `OrbTK` provides a [functional reactive-like][functional_reative] API. It depends on
//! the rust [`DCES`][dces] crate, that provides an Entity Component
//! System. Interaction with `DCES` is managed via the `Entity
//! Component Manager`(ECM), a wrapper API, that transparently mapps `OrbTK` widgets
//! to `ECM`  entities and `OrbTK` properties to `ECM` componets.
//!
//! The main goals of `OrbTk` are speed, ease of use, and cross-platform compatibility.
//!
//! Happy 🦀 hacking! ✨
//!
//! [dces]: https://docs.rs/dces
//! [functional_reative]: https://en.wikipedia.org/wiki/Functional_reactive_programming
//! [orbtk_planet]: https://raw.githubusercontent.com/rzerres/orbtk/wip_documentation/orbtk/images/orbtk_planet.svg
// //! [orbtk_planet]: https://raw.githubusercontent.com/redox-os/orbtk/develop/orbtk/images/orbtk_planet.svg

//#![feature(extern_doc)]
//#[doc(include="../README.md")]

pub use orbtk_orbclient::prelude::initialize;

pub mod core {
    pub use orbtk_core::application;
    pub use orbtk_core::localization;
    pub use orbtk_core::macros;
    pub use orbtk_core::prelude::*;
    pub use orbtk_core::theming;
    pub use orbtk_core::tree;
}

pub mod proc_macros {
    pub use orbtk_proc_macros::*;
}

pub mod render {
    pub use orbtk_tinyskia::*;
}

pub mod shell {
    pub use orbtk_orbclient::prelude::*;
}

pub mod utils {
    pub use orbtk_utils::*;
}

pub mod widgets {
    pub use orbtk_widgets::*;
}

pub mod prelude;

mod application;

pub use self::application::*;
<commit_msg>orbtk: typo correction<commit_after>#![crate_name = "orbtk"]
#![crate_type = "lib"]

//! # OrbTK - The Orbital Toolkit
//!
//! ![Welcome to the OrbTk planet.][orbtk_planet]
//!
//! The `OrbTK` crate implements a cross-platform (G)UI toolkit for
//! building scalable user interfaces. The codebase is natively build
//! with the `Rust` programming language.
//!
//! `OrbTK` provides a [functional reactive-like][functional_reative] API. It depends on
//! the rust [`DCES`][dces] crate, that provides an Entity Component
//! System. Interaction with `DCES` is managed via the `Entity
//! Component Manager`(ECM), a wrapper API, that transparently mapps `OrbTK` widgets
//! to `ECM`  entities and `OrbTK` properties to `ECM` components.
//!
//! The main goals of `OrbTk` are speed, ease of use, and cross-platform compatibility.
//!
//! Happy 🦀 hacking! ✨
//!
//! [dces]: https://docs.rs/dces
//! [functional_reative]: https://en.wikipedia.org/wiki/Functional_reactive_programming
//! [orbtk_planet]: https://raw.githubusercontent.com/rzerres/orbtk/wip_documentation/orbtk/images/orbtk_planet.svg
// //! [orbtk_planet]: https://raw.githubusercontent.com/redox-os/orbtk/develop/orbtk/images/orbtk_planet.svg

//#![feature(extern_doc)]
//#[doc(include="../README.md")]

pub use orbtk_orbclient::prelude::initialize;

pub mod core {
    pub use orbtk_core::application;
    pub use orbtk_core::localization;
    pub use orbtk_core::macros;
    pub use orbtk_core::prelude::*;
    pub use orbtk_core::theming;
    pub use orbtk_core::tree;
}

pub mod proc_macros {
    pub use orbtk_proc_macros::*;
}

pub mod render {
    pub use orbtk_tinyskia::*;
}

pub mod shell {
    pub use orbtk_orbclient::prelude::*;
}

pub mod utils {
    pub use orbtk_utils::*;
}

pub mod widgets {
    pub use orbtk_widgets::*;
}

pub mod prelude;

mod application;

pub use self::application::*;
<|endoftext|>


<commit_before>use super::super::common::initiate_validator_exit;
use super::Error;
use itertools::{Either, Itertools};
use types::*;

/// Performs a validator registry update, if required.
///
/// Spec v0.11.1
pub fn process_registry_updates<T: EthSpec>(
    state: &mut BeaconState<T>,
    spec: &ChainSpec,
) -> Result<(), Error> {
    // Process activation eligibility and ejections.
    // Collect eligible and exiting validators (we need to avoid mutating the state while iterating).
    // We assume it's safe to re-order the change in eligibility and `initiate_validator_exit`.
    // Rest assured exiting validators will still be exited in the same order as in the spec.
    let current_epoch = state.current_epoch();
    let is_exiting_validator = |validator: &Validator| {
        validator.is_active_at(current_epoch)
            && validator.effective_balance <= spec.ejection_balance
    };
    let (eligible_validators, exiting_validators): (Vec<_>, Vec<_>) = state
        .validators
        .iter()
        .enumerate()
        .filter(|(_, validator)| {
            validator.is_eligible_for_activation_queue(spec) || is_exiting_validator(validator)
        })
        .partition_map(|(index, validator)| {
            if validator.is_eligible_for_activation_queue(spec) {
                Either::Left(index)
            } else {
                Either::Right(index)
            }
        });
    for index in eligible_validators {
        state.validators[index].activation_eligibility_epoch = current_epoch + 1;
    }
    for index in exiting_validators {
        initiate_validator_exit(state, index, spec)?;
    }

    // Queue validators eligible for activation and not dequeued for activation prior to finalized epoch
    let activation_queue = state
        .validators
        .iter()
        .enumerate()
        .filter(|(_, validator)| validator.is_eligible_for_activation(state, spec))
        .sorted_by_key(|(index, validator)| (validator.activation_eligibility_epoch, *index))
        .map(|(index, _)| index)
        .collect_vec();

    // Dequeue validators for activation up to churn limit
    let churn_limit = state.get_churn_limit(spec)? as usize;
    let delayed_activation_epoch = state.compute_activation_exit_epoch(current_epoch, spec);
    for index in activation_queue.into_iter().take(churn_limit) {
        let validator = &mut state.validators[index];
        validator.activation_epoch = delayed_activation_epoch;
    }

    Ok(())
}
<commit_msg>Avoid implicit validator status assumption (#1188)<commit_after>use super::super::common::initiate_validator_exit;
use super::Error;
use itertools::Itertools;
use types::*;

/// Performs a validator registry update, if required.
///
/// Spec v0.11.1
pub fn process_registry_updates<T: EthSpec>(
    state: &mut BeaconState<T>,
    spec: &ChainSpec,
) -> Result<(), Error> {
    // Process activation eligibility and ejections.
    // Collect eligible and exiting validators (we need to avoid mutating the state while iterating).
    // We assume it's safe to re-order the change in eligibility and `initiate_validator_exit`.
    // Rest assured exiting validators will still be exited in the same order as in the spec.
    let current_epoch = state.current_epoch();
    let is_ejectable = |validator: &Validator| {
        validator.is_active_at(current_epoch)
            && validator.effective_balance <= spec.ejection_balance
    };
    let indices_to_update: Vec<_> = state
        .validators
        .iter()
        .enumerate()
        .filter(|(_, validator)| {
            validator.is_eligible_for_activation_queue(spec) || is_ejectable(validator)
        })
        .map(|(idx, _)| idx)
        .collect();

    for index in indices_to_update {
        if state.validators[index].is_eligible_for_activation_queue(spec) {
            state.validators[index].activation_eligibility_epoch = current_epoch + 1;
        }
        if is_ejectable(&state.validators[index]) {
            initiate_validator_exit(state, index, spec)?;
        }
    }

    // Queue validators eligible for activation and not dequeued for activation prior to finalized epoch
    let activation_queue = state
        .validators
        .iter()
        .enumerate()
        .filter(|(_, validator)| validator.is_eligible_for_activation(state, spec))
        .sorted_by_key(|(index, validator)| (validator.activation_eligibility_epoch, *index))
        .map(|(index, _)| index)
        .collect_vec();

    // Dequeue validators for activation up to churn limit
    let churn_limit = state.get_churn_limit(spec)? as usize;
    let delayed_activation_epoch = state.compute_activation_exit_epoch(current_epoch, spec);
    for index in activation_queue.into_iter().take(churn_limit) {
        let validator = &mut state.validators[index];
        validator.activation_epoch = delayed_activation_epoch;
    }

    Ok(())
}
<|endoftext|>