bazaar 3.5.2

Rust implementation of the Bazaar formats and protocols
Documentation
use super::path::{accessible_normalized_filename, inaccessible_normalized_filename};
use super::{chunks_to_lines, contains_whitespace, kind_from_stat_mode, StatKind};
use std::path::{Path, PathBuf};

#[test]
fn test_contains_whitespace() {
    assert!(contains_whitespace("hello world"));
    assert!(contains_whitespace("hello\tworld"));
    assert!(contains_whitespace("hello\nworld"));
    assert!(contains_whitespace("hello\rworld"));
    assert!(contains_whitespace("hello\u{000B}world"));
    assert!(contains_whitespace("hello\u{000C}world"));
    assert!(!contains_whitespace("helloworld"));
    assert!(!contains_whitespace(""));
}

#[test]
fn test_kind_from_stat_mode() {
    // Format bits OR-ed with permission bits; permissions must not affect kind.
    assert_eq!(kind_from_stat_mode(0o100000 | 0o644), StatKind::File);
    assert_eq!(kind_from_stat_mode(0o040000 | 0o755), StatKind::Directory);
    assert_eq!(kind_from_stat_mode(0o120000 | 0o777), StatKind::Symlink);
    assert_eq!(kind_from_stat_mode(0o010000 | 0o666), StatKind::Fifo);
    assert_eq!(kind_from_stat_mode(0o140000 | 0o666), StatKind::Socket);
    assert_eq!(kind_from_stat_mode(0o020000 | 0o666), StatKind::CharDevice);
    assert_eq!(kind_from_stat_mode(0o060000 | 0o666), StatKind::BlockDevice);
    assert_eq!(kind_from_stat_mode(0o644), StatKind::Unknown);
}

#[test]
fn test_stat_kind_as_str() {
    assert_eq!(StatKind::File.as_str(), "file");
    assert_eq!(StatKind::Directory.as_str(), "directory");
    assert_eq!(StatKind::Symlink.as_str(), "symlink");
    assert_eq!(StatKind::Fifo.as_str(), "fifo");
    assert_eq!(StatKind::Socket.as_str(), "socket");
    assert_eq!(StatKind::CharDevice.as_str(), "chardev");
    assert_eq!(StatKind::BlockDevice.as_str(), "block");
    assert_eq!(StatKind::Unknown.as_str(), "unknown");
}

fn assert_chunks_to_lines(input: Vec<&str>, expected: Vec<&str>) {
    let iter = input.iter().map(|l| Ok::<&[u8], String>(l.as_bytes()));
    let got = chunks_to_lines(iter);
    let got = got
        .map(|l| String::from_utf8_lossy(l.unwrap().as_ref()).to_string())
        .collect::<Vec<_>>();
    assert_eq!(got, expected);
}

#[test]
fn test_chunks_to_lines() {
    assert_chunks_to_lines(vec!["a"], vec!["a"]);
    assert_chunks_to_lines(vec!["a\n"], vec!["a\n"]);
    assert_chunks_to_lines(vec!["a\nb\n"], vec!["a\n", "b\n"]);
    assert_chunks_to_lines(vec!["a\n", "b\n"], vec!["a\n", "b\n"]);
    assert_chunks_to_lines(vec!["a", "\n", "b", "\n"], vec!["a\n", "b\n"]);
    assert_chunks_to_lines(vec!["a", "a", "\n", "b", "\n"], vec!["aa\n", "b\n"]);
    assert_chunks_to_lines(vec![""], vec![]);
}

#[test]
fn test_is_inside() {
    fn is_inside(path: &str, dir: &str) -> bool {
        super::path::is_inside(Path::new(path), Path::new(dir))
    }
    assert!(is_inside("a", "a"));
    assert!(!is_inside("a", "b"));
    assert!(is_inside("a", "a/b"));
    assert!(!is_inside("b", "a/b"));
    assert!(is_inside("a/b", "a/b"));
    assert!(!is_inside("a/b", "a/c"));
    assert!(is_inside("a/b", "a/b/c"));
    assert!(!is_inside("a/b/c", "a/b"));
    assert!(is_inside("", "a"));
    assert!(!is_inside("a", ""));
}

#[test]
fn test_is_inside_any() {
    fn is_inside_any(path: &str, dirs: &[&str]) -> bool {
        let dirs = dirs.iter().map(Path::new).collect::<Vec<&Path>>();
        super::path::is_inside_any(dirs.as_slice(), Path::new(path))
    }
    assert!(is_inside_any("a", &["a"]));
    assert!(!is_inside_any("a", &["b"]));
    assert!(is_inside_any("a/b", &["a"]));
    assert!(!is_inside_any("a/b", &["b"]));
    assert!(is_inside_any("a/b", &["a/b"]));
    assert!(!is_inside_any("a/b", &["a/c"]));
    assert!(!is_inside_any("a/b", &["a/b/c"]));
    assert!(is_inside_any("a/b/c", &["a/b"]));
    assert!(!is_inside_any("", &["a"]));
    assert!(is_inside_any("a", &[""]));
    assert!(is_inside_any("a", &["a", "b"]));
    assert!(is_inside_any("a", &["b", "a"]));
    assert!(!is_inside_any("a", &["b", "c"]));
}

#[test]
fn test_is_inside_or_parent_of_any() {
    fn is_inside_or_parent_of_any(path: &str, dirs: &[&str]) -> bool {
        let dirs = dirs.iter().map(Path::new).collect::<Vec<&Path>>();
        super::path::is_inside_or_parent_of_any(dirs.as_slice(), Path::new(path))
    }
    assert!(is_inside_or_parent_of_any("a", &["a"]));
    assert!(!is_inside_or_parent_of_any("a", &["b"]));
    assert!(is_inside_or_parent_of_any("a/b", &["a"]));
    assert!(!is_inside_or_parent_of_any("a/b", &["b"]));
    assert!(is_inside_or_parent_of_any("a/b", &["a/b"]));
    assert!(!is_inside_or_parent_of_any("a/b", &["a/c"]));
    assert!(is_inside_or_parent_of_any("a/b", &["a/b/c"]));
    assert!(is_inside_or_parent_of_any("a/b/c", &["a/b"]));
    assert!(is_inside_or_parent_of_any("", &["a"]));
    assert!(is_inside_or_parent_of_any("a", &[""]));
    assert!(is_inside_or_parent_of_any("a", &["a", "b"]));
    assert!(is_inside_or_parent_of_any("a", &["b", "a"]));
    assert!(!is_inside_or_parent_of_any("a", &["b", "c"]));
    assert!(is_inside_or_parent_of_any("a/b", &["a", "b"]));
    assert!(is_inside_or_parent_of_any("a/b", &["b", "a"]));
}

#[test]
fn test_inaccessible_normalized_filename() {
    assert_eq!(
        inaccessible_normalized_filename(Path::new("a/b")),
        Some((PathBuf::from("a/b"), true))
    );
    assert_eq!(
        inaccessible_normalized_filename(Path::new("a/µ")),
        Some((PathBuf::from("a/µ"), true))
    );
}

#[test]
fn test_access_normalized_filename() {
    assert_eq!(
        accessible_normalized_filename(Path::new("a/b")),
        Some((PathBuf::from("a/b"), true))
    );
    assert_eq!(
        accessible_normalized_filename(Path::new("a/µ")),
        Some((PathBuf::from("a/µ"), true))
    );
}