Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/devenv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,8 @@ mod tests {
use super::*;
use crate::store::drv::load_derivation_from_store;
#[cfg(unix)]
use crate::store::nar::tests::fixture_tree;
use crate::store::nar::tests::{Tree, tree};
use rstest::rstest;

fn fixture(name: &str) -> String {
fs::read_to_string(
Expand Down Expand Up @@ -617,9 +618,8 @@ mod tests {

// TODO: the script is for a POSIX shell and the test names its paths that way.
#[cfg(unix)]
#[test]
fn rc_script_rewrites_outputs_and_writes_attrs() {
let dir = fixture_tree("devenv-rc");
#[rstest]
fn rc_script_rewrites_outputs_and_writes_attrs(#[from(tree)] dir: Tree) {
let json: serde_json::Value = serde_json::from_str(
r#"{
"bashFunctions": {},
Expand Down
17 changes: 8 additions & 9 deletions src/flake/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,8 @@ mod tests {
use super::*;

use crate::source::scm;
use crate::store::nar::tests::fixture_tree;
use crate::store::nar::tests::{Tree, tree};
use rstest::rstest;

/// A path as the evaluator and a flake URL name it: `/C:/x` on Windows.
fn internal(p: &Path) -> String {
Expand All @@ -653,15 +654,14 @@ mod tests {
assert!(parse_attr_path("a.\"b").is_err());
}

#[test]
fn refs_resolve_against_cwd_and_home() {
let d = fixture_tree("flakeref");
#[rstest]
fn refs_resolve_against_cwd_and_home(#[from(tree)] d: Tree) {
fs::write(d.join("flake.nix"), b"{ outputs = _: {}; }").unwrap();
fs::create_dir_all(d.join("sub")).unwrap();
fs::write(d.join("sub/flake.nix"), b"{ outputs = _: {}; }").unwrap();
let cwd = &sys::path_to_internal(&d);
let r = parse_flake_ref(".#a.b", cwd, None).unwrap();
assert_eq!(r.dir, d);
assert_eq!(r.dir, *d);
assert_eq!(r.source, SourceRef::Path(d.clone()));
assert_eq!(r.attr, ["a", "b"]);
let r = parse_flake_ref("./sub", cwd, None).unwrap();
Expand Down Expand Up @@ -704,9 +704,8 @@ mod tests {
assert!(!is_flake_ref("x.nix"));
}

#[test]
fn a_pinned_checkout_is_its_revision() {
let d = fixture_tree("flakeref-git");
#[rstest]
fn a_pinned_checkout_is_its_revision(#[from(tree)] d: Tree) {
fs::write(d.join("flake.nix"), b"{ outputs = _: {}; }").unwrap();
fs::create_dir_all(d.join("sub")).unwrap();
fs::write(d.join("sub/flake.nix"), b"{ outputs = _: {}; }").unwrap();
Expand All @@ -716,7 +715,7 @@ mod tests {
let url = format!("git+file://{}", internal(&d));

let r = parse_flake_ref(&format!("{url}?ref=HEAD&rev={rev}#a"), b"/", None).unwrap();
assert_eq!(r.dir, d);
assert_eq!(r.dir, *d);
assert_eq!(r.attr, ["a"]);
assert_eq!(
r.source,
Expand Down
8 changes: 4 additions & 4 deletions src/remote/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -507,12 +507,12 @@ fn hash_sources(sources: &[&StorePath], infos: &[SourceOrigin]) -> Result<Vec<Ob
#[cfg(test)]
mod tests {
use super::*;
use crate::store::nar::tests::fixture_tree;
use crate::store::nar::tests::{Tree, tree};
use crate::store::nar::{nar_hash, nar_size};
use rstest::rstest;

#[test]
fn hash_source_matches_nar_hash() {
let tree = fixture_tree("plan");
#[rstest]
fn hash_source_matches_nar_hash(tree: Tree) {
let (h, size) = hash_source(&SrcPath::fs(tree.clone(), None)).unwrap();
assert_eq!(h, nar_hash(&tree).unwrap());
assert_eq!(size, nar_size(&tree).unwrap());
Expand Down
8 changes: 4 additions & 4 deletions src/source/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ mod tests {
use std::time::{Duration, SystemTime};

use crate::store::hash;
use crate::store::nar::tests::fixture_tree;
use crate::store::nar::tests::{Tree, tree};
use rstest::rstest;

/// Only the fixed-output path of the hash itself skips the walk: another
/// hash under the same name, another name, a path below it and a
Expand All @@ -318,9 +319,8 @@ mod tests {
assert_eq!(v, ["/r/a", "/r/a/b", "/r/a/b/c.nix", "/r/d.nix"]);
}

#[test]
fn max_mtime_covers_root_and_children() {
let d = fixture_tree("mtime");
#[rstest]
fn max_mtime_covers_root_and_children(#[from(tree)] d: Tree) {
let f = d.join("newest");
fs::write(&f, b"x").unwrap();
let later = SystemTime::now() + Duration::from_secs(1000);
Expand Down
8 changes: 4 additions & 4 deletions src/source/scm/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,8 +475,9 @@ impl Scm for Git {
mod tests {
use crate::flake::parse_flake_ref;
use crate::source::SourceRef;
use crate::store::nar::tests::fixture_tree;
use crate::store::nar::tests::{Tree, tree};
use crate::sys;
use rstest::rstest;

use std::path::Path;

Expand All @@ -487,9 +488,8 @@ mod tests {

use std::fs;

#[test]
fn a_directory_in_a_repository_is_found() {
let d = fixture_tree("git-root");
#[rstest]
fn a_directory_in_a_repository_is_found(#[from(tree)] d: Tree) {
fs::write(d.join("sub/flake.nix"), b"{ outputs = _: {}; }").unwrap();
fs::create_dir_all(d.join(".git")).unwrap();
let r = parse_flake_ref(&format!("{}/sub#x", internal(&d)), b"/", None).unwrap();
Expand Down
84 changes: 46 additions & 38 deletions src/store/nar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -878,40 +878,56 @@ pub fn nar_hash_of_string(contents: &[u8]) -> Hash {
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use crate::sys;
use crate::sys::fs::set_executable;
use rstest::rstest;
use rstest::{fixture, rstest};
use std::env;
use std::ops::Deref;
use std::path::PathBuf;
use tempfile::tempdir;
use tempfile::{TempDir, tempdir};

/// Builds the fixture tree used by the shell commands in the test comments:
/// The tree the shell commands in the test comments build:
/// mkdir -p tree/sub; printf 'hello world\n' > tree/a.txt;
/// printf '#!/bin/sh\necho hi\n' > tree/run.sh; chmod +x tree/run.sh;
/// ln -s a.txt tree/link; : > tree/sub/empty; printf zzz > tree/sub/z
pub(crate) fn fixture_tree(tag: &str) -> PathBuf {
fixture_tree_with(tag, true)
pub(crate) struct Tree {
path: PathBuf,
_dir: TempDir,
}

impl Deref for Tree {
type Target = PathBuf;
fn deref(&self) -> &PathBuf {
&self.path
}
}

impl AsRef<Path> for Tree {
fn as_ref(&self) -> &Path {
&self.path
}
}

/// `exec` is whether `run.sh` has the executable bit, which Windows cannot set.
fn fixture_tree_with(tag: &str, exec: bool) -> PathBuf {
let dir = sys::temp_dir().join(format!("iets-nar-{}-{tag}", std::process::id()));
let _ = fs::remove_dir_all(&dir);
let tree = dir.join("tree");
#[fixture]
pub(crate) fn tree(#[default(true)] exec: bool) -> Tree {
let dir = tempdir().unwrap();
let tree = dir.path().join("tree");
fs::create_dir_all(tree.join("sub")).unwrap();
fs::write(tree.join("a.txt"), b"hello world\n").unwrap();
fs::write(tree.join("run.sh"), b"#!/bin/sh\necho hi\n").unwrap();
set_executable(&tree.join("run.sh"), exec).unwrap();
symlink("a.txt", tree.join("link")).unwrap();
fs::write(tree.join("sub/empty"), b"").unwrap();
fs::write(tree.join("sub/z"), b"zzz").unwrap();
tree
Tree {
path: tree,
_dir: dir,
}
}

// nix-store --dump tree | sha256sum ; nix-store --dump tree | wc -c
#[test]
fn directory_nar() {
let tree = fixture_tree_with("dir", false);
#[rstest]
fn directory_nar(#[with(false)] tree: Tree) {
assert_eq!(
nar_hash(&tree).unwrap().to_base16(),
"5bd341428326a5608117fb128d3114fc3fb6c76de99cd19c10397bdad728beae"
Expand All @@ -921,9 +937,8 @@ pub(crate) mod tests {

// the same with `chmod +x tree/run.sh`
#[cfg(unix)]
#[test]
fn directory_nar_with_an_executable() {
let tree = fixture_tree("dir-x");
#[rstest]
fn directory_nar_with_an_executable(tree: Tree) {
assert_eq!(
nar_hash(&tree).unwrap().to_base16(),
"9db4d4d873838f1fbb8f363841597d61244beebb19bd10b606ae2a6d4b940ede"
Expand All @@ -932,9 +947,8 @@ pub(crate) mod tests {
}

// nix hash path tree ; nix hash path --base32 tree
#[test]
fn directory_nar_hash_formats() {
let tree = fixture_tree_with("fmt", false);
#[rstest]
fn directory_nar_hash_formats(#[with(false)] tree: Tree) {
let h = nar_hash(&tree).unwrap();
assert_eq!(
h.to_sri(),
Expand All @@ -947,18 +961,16 @@ pub(crate) mod tests {
}

// nix-store --dump tree/a.txt | sha256sum
#[test]
fn regular_file_nar() {
let tree = fixture_tree("file");
#[rstest]
fn regular_file_nar(tree: Tree) {
let expected = "34ca3ac63094d1d5751f741101692a78f95eedf10744b088129fc324dfd0f603";
assert_eq!(nar_hash(&tree.join("a.txt")).unwrap().to_base16(), expected);
assert_eq!(nar_hash_of_string(b"hello world\n").to_base16(), expected);
}

// nix-store --dump tree/run.sh | sha256sum
#[test]
fn script_nar() {
let tree = fixture_tree_with("script", false);
#[rstest]
fn script_nar(#[with(false)] tree: Tree) {
assert_eq!(
nar_hash(&tree.join("run.sh")).unwrap().to_base16(),
"e519505edb9f77f7f02efefd3c9b29766fdd0f449e9bf932313d39ce249982e9"
Expand All @@ -967,19 +979,17 @@ pub(crate) mod tests {

// the same after `chmod +x tree/run.sh`
#[cfg(unix)]
#[test]
fn executable_file_nar() {
let tree = fixture_tree("exec");
#[rstest]
fn executable_file_nar(tree: Tree) {
assert_eq!(
nar_hash(&tree.join("run.sh")).unwrap().to_base16(),
"5e0accf02cedede5e4119ffa15e79e79a5fb1fb9bc43c3d434f33227a14477a0"
);
}

// nix-store --dump tree/link | sha256sum
#[test]
fn symlink_nar() {
let tree = fixture_tree("link");
#[rstest]
fn symlink_nar(tree: Tree) {
assert_eq!(
nar_hash(&tree.join("link")).unwrap().to_base16(),
"8d3c00cfa866e4d1b809772afeac240786246221eb2c574d69c4bba168834e81"
Expand Down Expand Up @@ -1028,9 +1038,8 @@ pub(crate) mod tests {
}

// nix-store --dump tree | nix-store --restore out ; nix-store --dump out | sha256sum
#[test]
fn restore_roundtrip() {
let tree = fixture_tree("restore");
#[rstest]
fn restore_roundtrip(tree: Tree) {
let mut nar = Vec::new();
dump_path(&tree, &mut nar, &mut |_, _| true).unwrap();
let out = tree.with_file_name("restored");
Expand All @@ -1054,9 +1063,8 @@ pub(crate) mod tests {
assert!(restore_path(&mut &b"nix-archive-2"[..], &out).is_err());
}

#[test]
fn filter_sees_types_and_paths() {
let tree = fixture_tree("filter");
#[rstest]
fn filter_sees_types_and_paths(tree: Tree) {
let mut seen = Vec::new();
let (_, _) = nar_hash_filtered(&tree, HashAlgo::Sha256, &mut |p, t| {
seen.push((p.strip_prefix(&tree).unwrap().to_path_buf(), t));
Expand Down
24 changes: 10 additions & 14 deletions src/store/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ mod tests {
use super::*;
use crate::store::nar::nar_hash;
use crate::store::nar::nar_hash_filtered;
use crate::store::nar::tests::fixture_tree;
use crate::store::nar::tests::{Tree, tree};

fn set(paths: &[&str]) -> BTreeSet<StorePath> {
paths.iter().map(|p| StorePath::parse(p).unwrap()).collect()
Expand Down Expand Up @@ -482,10 +482,9 @@ mod tests {
);
}

// nix-instantiate --eval -E '"${./tree}"' (tree from nar.rs fixture_tree)
#[test]
fn path_copy_directory() {
let tree = fixture_tree("pathcopy");
// nix-instantiate --eval -E '"${./tree}"' (tree from the nar.rs fixture)
#[rstest]
fn path_copy_directory(tree: Tree) {
let h = nar_hash(&tree).unwrap();
let p = make_fixed_output_path(IngestionMethod::Recursive, &h, "tree", &BTreeSet::new())
.unwrap();
Expand All @@ -498,9 +497,8 @@ mod tests {
}

// nix-instantiate --eval -E '"${./tree/a.txt}"'
#[test]
fn path_copy_file() {
let tree = fixture_tree("pathfile");
#[rstest]
fn path_copy_file(tree: Tree) {
let h = nar_hash(&tree.join("a.txt")).unwrap();
let p = make_fixed_output_path(IngestionMethod::Recursive, &h, "a.txt", &BTreeSet::new())
.unwrap();
Expand All @@ -511,9 +509,8 @@ mod tests {
}

// nix-instantiate --eval -E '"${builtins.filterSource (p: t: baseNameOf p != "sub") ./tree}"'
#[test]
fn filter_source() {
let tree = fixture_tree("filtersrc");
#[rstest]
fn filter_source(tree: Tree) {
let (h, _) = nar_hash_filtered(&tree, HashAlgo::Sha256, &mut |p, _| {
p.file_name().unwrap() != "sub"
})
Expand All @@ -528,9 +525,8 @@ mod tests {
}

// nix-instantiate --eval -E '"${builtins.path { path = ./tree; name = "mytree"; }}"'
#[test]
fn path_with_name() {
let tree = fixture_tree("pathname");
#[rstest]
fn path_with_name(tree: Tree) {
let h = nar_hash(&tree).unwrap();
let p = make_fixed_output_path(IngestionMethod::Recursive, &h, "mytree", &BTreeSet::new())
.unwrap();
Expand Down
13 changes: 6 additions & 7 deletions src/trace/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,8 @@ mod tests {

use std::time::Instant;

use crate::store::nar::tests::fixture_tree;
use crate::store::nar::tests::{Tree, tree};
use rstest::rstest;

#[test]
fn dedupe_keeps_conflicting_values() {
Expand Down Expand Up @@ -912,9 +913,8 @@ mod tests {

/// The fused fingerprint must be byte-identical to the separate walk, or
/// every cache entry a dump writes would miss on validation.
#[test]
fn dump_fingerprint_matches_the_separate_walk() {
let dir = fixture_tree("trace-fused");
#[rstest]
fn dump_fingerprint_matches_the_separate_walk(#[from(tree)] dir: Tree) {
for accepted in [
None,
Some(
Expand All @@ -937,9 +937,8 @@ mod tests {
}
}

#[test]
fn fingerprint_changes_with_content_size_and_seen_entries() {
let dir = fixture_tree("trace-fp");
#[rstest]
fn fingerprint_changes_with_content_size_and_seen_entries(#[from(tree)] dir: Tree) {
let (a, sa) = tree_fingerprint(&dir, None).unwrap();
let (b, sb) = tree_fingerprint(&dir, None).unwrap();
assert_eq!((a, sa), (b, sb));
Expand Down
Loading
Loading