nix-nar-cli 0.3.0

Binary to manipulate Nix Archive (nar) files
//! Tests to check that `nix-nar ls` outputs the same thing as `nix
//! nar ls`.

use crate::cmd_ls::{self, Opts};
use camino::Utf8Path;
use insta::assert_snapshot;

#[test]
fn test_ls() {
    fn run_ls(path: &str) -> Result<String, anyhow::Error> {
        let mut output: Vec<u8> = vec![];
        let opts = Opts {
            json: false,
            long: false,
            recursive: false,
            nar: Utf8Path::new("test-data/07-nested-dirs.nar").to_path_buf(),
            path: Utf8Path::new(path).to_path_buf(),
        };
        cmd_ls::run(&mut output, opts)?;
        Ok(std::str::from_utf8(&output)?.to_string())
    }
    assert_snapshot!(run_ls("/").unwrap(), @r###"
    ./01-an-empty-file
    ./02-some-dir
    ./03-executable-file.exe
    "###);
    assert_snapshot!(run_ls("/01-an-empty-file").unwrap(), @r###"
    01-an-empty-file
    "###);
    assert_snapshot!(run_ls("/02-some-dir").unwrap(), @r###"
    ./link-to-an-empty-file
    ./more-depth
    ./small-file
    "###);
    assert_snapshot!(run_ls("/03-executable-file.exe").unwrap(), @r###"
    03-executable-file.exe
    "###);
    assert_snapshot!(run_ls("/02-some-dir/link-to-an-empty-file").unwrap(), @r###"
    link-to-an-empty-file
    "###);
    assert_snapshot!(run_ls("/02-some-dir/more-depth").unwrap(), @r###"
    ./deep-empty-file
    "###);
    assert_snapshot!(run_ls("/02-some-dir/small-file").unwrap(), @r###"
    small-file
    "###);
    assert_snapshot!(run_ls("/02-some-dir/more-depth/deep-empty-file").unwrap(), @r###"
    deep-empty-file
    "###);
}

#[test]
fn test_ls_r() {
    fn run_ls(path: &str) -> Result<String, anyhow::Error> {
        let mut output: Vec<u8> = vec![];
        let opts = Opts {
            json: false,
            long: false,
            recursive: true,
            nar: Utf8Path::new("test-data/07-nested-dirs.nar").to_path_buf(),
            path: Utf8Path::new(path).to_path_buf(),
        };
        cmd_ls::run(&mut output, opts)?;
        Ok(std::str::from_utf8(&output)?.to_string())
    }
    assert_snapshot!(run_ls("/").unwrap(), @r###"
    ./01-an-empty-file
    ./02-some-dir
    ./02-some-dir/link-to-an-empty-file
    ./02-some-dir/more-depth
    ./02-some-dir/more-depth/deep-empty-file
    ./02-some-dir/small-file
    ./03-executable-file.exe
    "###);
    assert_snapshot!(run_ls("/01-an-empty-file").unwrap(), @r###"
    01-an-empty-file
    "###);
    assert_snapshot!(run_ls("/02-some-dir").unwrap(), @r###"
    ./link-to-an-empty-file
    ./more-depth
    ./more-depth/deep-empty-file
    ./small-file
    "###);
    assert_snapshot!(run_ls("/03-executable-file.exe").unwrap(), @r###"
    03-executable-file.exe
    "###);
    assert_snapshot!(run_ls("/02-some-dir/link-to-an-empty-file").unwrap(), @r###"
    link-to-an-empty-file
    "###);
    assert_snapshot!(run_ls("/02-some-dir/more-depth").unwrap(), @r###"
    ./deep-empty-file
    "###);
    assert_snapshot!(run_ls("/02-some-dir/small-file").unwrap(), @r###"
    small-file
    "###);
    assert_snapshot!(run_ls("/02-some-dir/more-depth/deep-empty-file").unwrap(), @r###"
    deep-empty-file
    "###);
}

#[test]
fn test_ls_rl() {
    fn run_ls(path: &str) -> Result<String, anyhow::Error> {
        let mut output: Vec<u8> = vec![];
        let opts = Opts {
            json: false,
            long: true,
            recursive: true,
            nar: Utf8Path::new("test-data/07-nested-dirs.nar").to_path_buf(),
            path: Utf8Path::new(path).to_path_buf(),
        };
        cmd_ls::run(&mut output, opts)?;
        Ok(std::str::from_utf8(&output)?.to_string())
    }
    assert_snapshot!(run_ls("/").unwrap(), @r###"
    -r--r--r--                    0 ./01-an-empty-file
    dr-xr-xr-x                    0 ./02-some-dir
    lrwxrwxrwx                    0 ./02-some-dir/link-to-an-empty-file -> ../01-an-empty-file
    dr-xr-xr-x                    0 ./02-some-dir/more-depth
    -r--r--r--                    0 ./02-some-dir/more-depth/deep-empty-file
    -r--r--r--                   21 ./02-some-dir/small-file
    -r-xr-xr-x                    0 ./03-executable-file.exe
    "###);
    assert_snapshot!(run_ls("/01-an-empty-file").unwrap(), @r###"
    -r--r--r--                    0 01-an-empty-file
    "###);
    assert_snapshot!(run_ls("/02-some-dir").unwrap(), @r###"
    lrwxrwxrwx                    0 ./link-to-an-empty-file -> ../01-an-empty-file
    dr-xr-xr-x                    0 ./more-depth
    -r--r--r--                    0 ./more-depth/deep-empty-file
    -r--r--r--                   21 ./small-file
    "###);
    assert_snapshot!(run_ls("/03-executable-file.exe").unwrap(), @r###"
    -r-xr-xr-x                    0 03-executable-file.exe
    "###);
    assert_snapshot!(run_ls("/02-some-dir/link-to-an-empty-file").unwrap(), @"lrwxrwxrwx                    0 link-to-an-empty-file -> ../01-an-empty-file
");
    assert_snapshot!(run_ls("/02-some-dir/more-depth").unwrap(), @r###"
    -r--r--r--                    0 ./deep-empty-file
    "###);
    assert_snapshot!(run_ls("/02-some-dir/small-file").unwrap(), @r###"
    -r--r--r--                   21 small-file
    "###);
    assert_snapshot!(run_ls("/02-some-dir/more-depth/deep-empty-file").unwrap(), @r###"
    -r--r--r--                    0 deep-empty-file
    "###);
}

#[test]
fn test_ls_json() {
    fn run_ls(path: &str) -> Result<String, anyhow::Error> {
        let mut output: Vec<u8> = vec![];
        let opts = Opts {
            json: true,
            long: false,
            recursive: false,
            nar: Utf8Path::new("test-data/07-nested-dirs.nar").to_path_buf(),
            path: Utf8Path::new(path).to_path_buf(),
        };
        cmd_ls::run(&mut output, opts)?;
        Ok(std::str::from_utf8(&output)?.to_string())
    }
    assert_snapshot!(
        run_ls("/").unwrap(),
        @r###"{"entries":{"01-an-empty-file":{},"02-some-dir":{},"03-executable-file.exe":{}},"type":"directory"}"###
    );
    assert_snapshot!(
        run_ls("/01-an-empty-file").unwrap(),
        @r###"{"narOffset":240,"size":0,"type":"regular"}"###
    );
    assert_snapshot!(
        run_ls("/02-some-dir").unwrap(),
        @r###"{"entries":{"link-to-an-empty-file":{},"more-depth":{},"small-file":{}},"type":"directory"}"###
    );
    assert_snapshot!(
        run_ls("/03-executable-file.exe").unwrap(),
        @r###"{"executable":true,"narOffset":1456,"size":0,"type":"regular"}"###
    );
    assert_snapshot!(
        run_ls("/02-some-dir/link-to-an-empty-file").unwrap(),
        @r###"{"target":"../01-an-empty-file","type":"symlink"}"###
    );
    assert_snapshot!(
        run_ls("/02-some-dir/more-depth").unwrap(),
        @r###"{"entries":{"deep-empty-file":{}},"type":"directory"}"###
    );
    assert_snapshot!(
        run_ls("/02-some-dir/small-file").unwrap(),
        @r###"{"narOffset":1168,"size":21,"type":"regular"}"###);
    assert_snapshot!(
        run_ls("/02-some-dir/more-depth/deep-empty-file").unwrap(),
        @r###"{"narOffset":944,"size":0,"type":"regular"}"###
    );
}

#[test]
fn test_ls_json_r() {
    fn run_ls(path: &str) -> Result<String, anyhow::Error> {
        let mut output: Vec<u8> = vec![];
        let opts = Opts {
            json: true,
            long: false,
            recursive: true,
            nar: Utf8Path::new("test-data/07-nested-dirs.nar").to_path_buf(),
            path: Utf8Path::new(path).to_path_buf(),
        };
        cmd_ls::run(&mut output, opts)?;
        Ok(std::str::from_utf8(&output)?.to_string())
    }
    assert_snapshot!(
        run_ls("/").unwrap(),
        @r###"{"entries":{"01-an-empty-file":{"narOffset":240,"size":0,"type":"regular"},"02-some-dir":{"entries":{"link-to-an-empty-file":{"target":"../01-an-empty-file","type":"symlink"},"more-depth":{"entries":{"deep-empty-file":{"narOffset":944,"size":0,"type":"regular"}},"type":"directory"},"small-file":{"narOffset":1168,"size":21,"type":"regular"}},"type":"directory"},"03-executable-file.exe":{"executable":true,"narOffset":1456,"size":0,"type":"regular"}},"type":"directory"}"###
    );
    assert_snapshot!(
        run_ls("/01-an-empty-file").unwrap(),
        @r###"{"narOffset":240,"size":0,"type":"regular"}"###
    );
    assert_snapshot!(
        run_ls("/02-some-dir").unwrap(),
        @r###"{"entries":{"link-to-an-empty-file":{"target":"../01-an-empty-file","type":"symlink"},"more-depth":{"entries":{"deep-empty-file":{"narOffset":944,"size":0,"type":"regular"}},"type":"directory"},"small-file":{"narOffset":1168,"size":21,"type":"regular"}},"type":"directory"}"###
    );
    assert_snapshot!(
        run_ls("/03-executable-file.exe").unwrap(),
        @r###"{"executable":true,"narOffset":1456,"size":0,"type":"regular"}"###
    );
    assert_snapshot!(
        run_ls("/02-some-dir/link-to-an-empty-file").unwrap(),
        @r###"{"target":"../01-an-empty-file","type":"symlink"}"###
    );
    assert_snapshot!(
        run_ls("/02-some-dir/more-depth").unwrap(),
        @r###"{"entries":{"deep-empty-file":{"narOffset":944,"size":0,"type":"regular"}},"type":"directory"}"###
    );
    assert_snapshot!(
        run_ls("/02-some-dir/small-file").unwrap(),
        @r###"{"narOffset":1168,"size":21,"type":"regular"}"###);
    assert_snapshot!(
        run_ls("/02-some-dir/more-depth/deep-empty-file").unwrap(),
        @r###"{"narOffset":944,"size":0,"type":"regular"}"###
    );
}

#[test]
fn test_ls_error() {
    fn run_ls(path: &str) -> Result<String, anyhow::Error> {
        let mut output: Vec<u8> = vec![];
        let opts = Opts {
            json: false,
            long: false,
            recursive: false,
            nar: Utf8Path::new("test-data/07-nested-dirs.nar").to_path_buf(),
            path: Utf8Path::new(path).to_path_buf(),
        };
        match cmd_ls::run(&mut output, opts) {
            Ok(()) => Ok(std::str::from_utf8(&output)?.to_string()),
            Err(err) => Ok(format!("Returned Err: {err}")),
        }
    }
    assert_snapshot!(
        run_ls("meh").unwrap(),
        @"Returned Err: path 'meh' does not exist"
    );
    assert_snapshot!(
        run_ls("/meh").unwrap(),
        @"Returned Err: path '/meh' does not exist"
    );
}

#[test]
fn test_ls_json_error() {
    fn run_ls(path: &str) -> Result<String, anyhow::Error> {
        let mut output: Vec<u8> = vec![];
        let opts = Opts {
            json: true,
            long: false,
            recursive: false,
            nar: Utf8Path::new("test-data/07-nested-dirs.nar").to_path_buf(),
            path: Utf8Path::new(path).to_path_buf(),
        };
        match cmd_ls::run(&mut output, opts) {
            Ok(()) => Ok(std::str::from_utf8(&output)?.to_string()),
            Err(err) => Ok(format!("Returned Err: {err}")),
        }
    }
    assert_snapshot!(
        run_ls("meh").unwrap(),
        @"{}"
    );
    assert_snapshot!(
        run_ls("/meh").unwrap(),
        @"{}"
    );
}