From 3cdde8ad5a4650cbb248b070891daf72ccfc9af0 Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Wed, 13 Dec 2023 11:34:17 +0200 Subject: [PATCH] feat(tvix/glue): add some import tests This creates a directory with a .keep file inside, and uses "${path/to/there}" to coerce it to a string (and import it into the store), ensuring it calculates the same store paths as Nix does. Change-Id: Ie14ae075104ce278bc4f2cce93aab5762a2734d1 Reviewed-on: https://cl.tvl.fyi/c/depot/+/10343 Tested-by: BuildkiteCI Autosubmit: flokli Reviewed-by: raitobezarius --- tvix/Cargo.lock | 52 ++++++--- tvix/Cargo.nix | 200 ++++++++++++++++++++++++++++----- tvix/glue/Cargo.toml | 1 + tvix/glue/src/tvix_store_io.rs | 90 +++++++++++++++ 4 files changed, 301 insertions(+), 42 deletions(-) diff --git a/tvix/Cargo.lock b/tvix/Cargo.lock index 1df6d199a..9a0f05193 100644 --- a/tvix/Cargo.lock +++ b/tvix/Cargo.lock @@ -794,12 +794,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fd-lock" @@ -808,7 +805,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39ae6b3d9530211fb3b12a95374b8b0823be812f53d09e18c5675c0146b09642" dependencies = [ "cfg-if", - "rustix", + "rustix 0.37.19", "windows-sys 0.48.0", ] @@ -1236,7 +1233,7 @@ checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", - "rustix", + "rustix 0.37.19", "windows-sys 0.48.0", ] @@ -1361,6 +1358,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + [[package]] name = "litrs" version = "0.2.3" @@ -2034,6 +2037,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_users" version = "0.4.3" @@ -2178,7 +2190,20 @@ dependencies = [ "errno", "io-lifetimes", "libc", - "linux-raw-sys", + "linux-raw-sys 0.3.7", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys 0.4.12", "windows-sys 0.48.0", ] @@ -2619,15 +2644,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.5.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", - "rustix", - "windows-sys 0.45.0", + "redox_syscall 0.4.1", + "rustix 0.38.21", + "windows-sys 0.48.0", ] [[package]] @@ -3164,6 +3189,7 @@ dependencies = [ "criterion", "lazy_static", "nix-compat", + "tempfile", "test-case", "thiserror", "tokio", diff --git a/tvix/Cargo.nix b/tvix/Cargo.nix index 91709258e..c7957403e 100644 --- a/tvix/Cargo.nix +++ b/tvix/Cargo.nix @@ -879,6 +879,7 @@ rec { "rustc-dep-of-std" = [ "core" "compiler_builtins" ]; "serde" = [ "dep:serde" ]; }; + resolvedDefaultFeatures = [ "std" ]; }; "bitmaps" = rec { crateName = "bitmaps"; @@ -2283,6 +2284,7 @@ rec { features = { "default" = [ "std" ]; }; + resolvedDefaultFeatures = [ "std" ]; }; "errno-dragonfly" = rec { crateName = "errno-dragonfly"; @@ -2330,28 +2332,19 @@ rec { }; "fastrand" = rec { crateName = "fastrand"; - version = "1.9.0"; + version = "2.0.1"; edition = "2018"; - sha256 = "1gh12m56265ihdbzh46bhh0jf74i197wm51jg1cw75q7ggi96475"; + sha256 = "19flpv5zbzpf0rk4x77z4zf25in0brg8l7m304d3yrf47qvwxjr5"; authors = [ "Stjepan Glavina " ]; - dependencies = [ - { - name = "instant"; - packageId = "instant"; - target = { target, features }: (("wasm32" == target."arch" or null) && (!("wasi" == target."os" or null))); - } - ]; - devDependencies = [ - { - name = "instant"; - packageId = "instant"; - target = { target, features }: (("wasm32" == target."arch" or null) && (!("wasi" == target."os" or null))); - features = [ "wasm-bindgen" ]; - } - ]; - + features = { + "default" = [ "std" ]; + "getrandom" = [ "dep:getrandom" ]; + "js" = [ "std" "getrandom" ]; + "std" = [ "alloc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "std" ]; }; "fd-lock" = rec { crateName = "fd-lock"; @@ -2368,7 +2361,7 @@ rec { } { name = "rustix"; - packageId = "rustix"; + packageId = "rustix 0.37.19"; target = { target, features }: (target."unix" or false); features = [ "fs" ]; } @@ -3761,7 +3754,7 @@ rec { } { name = "rustix"; - packageId = "rustix"; + packageId = "rustix 0.37.19"; target = { target, features }: (!((target."windows" or false) || ("hermit" == target."os" or null) || ("unknown" == target."os" or null))); features = [ "termios" ]; } @@ -4113,7 +4106,7 @@ rec { }; resolvedDefaultFeatures = [ "default" ]; }; - "linux-raw-sys" = rec { + "linux-raw-sys 0.3.7" = rec { crateName = "linux-raw-sys"; version = "0.3.7"; edition = "2018"; @@ -4129,6 +4122,22 @@ rec { }; resolvedDefaultFeatures = [ "errno" "general" "ioctl" "no_std" ]; }; + "linux-raw-sys 0.4.12" = rec { + crateName = "linux-raw-sys"; + version = "0.4.12"; + edition = "2021"; + sha256 = "0mhlla3gk1jgn6mrq9s255rvvq8a1w3yk2vpjiwsd6hmmy1imkf4"; + authors = [ + "Dan Gohman " + ]; + features = { + "compiler_builtins" = [ "dep:compiler_builtins" ]; + "core" = [ "dep:core" ]; + "default" = [ "std" "general" "errno" ]; + "rustc-dep-of-std" = [ "core" "compiler_builtins" "no_std" ]; + }; + resolvedDefaultFeatures = [ "elf" "errno" "general" "ioctl" "no_std" ]; + }; "litrs" = rec { crateName = "litrs"; version = "0.2.3"; @@ -6007,6 +6016,26 @@ rec { "rustc-dep-of-std" = [ "core" "bitflags/rustc-dep-of-std" ]; }; }; + "redox_syscall 0.4.1" = rec { + crateName = "redox_syscall"; + version = "0.4.1"; + edition = "2018"; + sha256 = "1aiifyz5dnybfvkk4cdab9p2kmphag1yad6iknc7aszlxxldf8j7"; + libName = "syscall"; + authors = [ + "Jeremy Soller " + ]; + dependencies = [ + { + name = "bitflags"; + packageId = "bitflags 1.3.2"; + } + ]; + features = { + "core" = [ "dep:core" ]; + "rustc-dep-of-std" = [ "core" "bitflags/rustc-dep-of-std" ]; + }; + }; "redox_users" = rec { crateName = "redox_users"; version = "0.4.3"; @@ -6580,7 +6609,7 @@ rec { ]; }; - "rustix" = rec { + "rustix 0.37.19" = rec { crateName = "rustix"; version = "0.37.19"; edition = "2018"; @@ -6638,14 +6667,14 @@ rec { } { name = "linux-raw-sys"; - packageId = "linux-raw-sys"; + packageId = "linux-raw-sys 0.3.7"; usesDefaultFeatures = false; target = { target, features }: ((("android" == target."os" or null) || ("linux" == target."os" or null)) && ((target."rustix_use_libc" or false) || (target."miri" or false) || (!(("linux" == target."os" or null) && (("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || (("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("powerpc64" == target."arch" or null) || ("riscv64" == target."arch" or null) || ("mips" == target."arch" or null) || ("mips64" == target."arch" or null)))))))); features = [ "general" "ioctl" "no_std" ]; } { name = "linux-raw-sys"; - packageId = "linux-raw-sys"; + packageId = "linux-raw-sys 0.3.7"; usesDefaultFeatures = false; target = { target, features }: ((!(target."rustix_use_libc" or false)) && (!(target."miri" or false)) && ("linux" == target."os" or null) && (("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || (("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("powerpc64" == target."arch" or null) || ("riscv64" == target."arch" or null) || ("mips" == target."arch" or null) || ("mips64" == target."arch" or null))))); features = [ "general" "errno" "ioctl" "no_std" ]; @@ -6701,6 +6730,115 @@ rec { }; resolvedDefaultFeatures = [ "default" "fs" "io-lifetimes" "libc" "std" "termios" "use-libc-auxv" ]; }; + "rustix 0.38.21" = rec { + crateName = "rustix"; + version = "0.38.21"; + edition = "2021"; + sha256 = "18q2mx7gnnl1238psb1r0avdw00l8y0jxkxgimyhmmg50q2nnhib"; + authors = [ + "Dan Gohman " + "Jakub Konka " + ]; + dependencies = [ + { + name = "bitflags"; + packageId = "bitflags 2.4.1"; + usesDefaultFeatures = false; + } + { + name = "errno"; + packageId = "errno"; + rename = "libc_errno"; + optional = true; + usesDefaultFeatures = false; + target = { target, features }: ((!(target."rustix_use_libc" or false)) && (!(target."miri" or false)) && ("linux" == target."os" or null) && ("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("riscv64" == target."arch" or null) || ((target."rustix_use_experimental_asm" or false) && ("powerpc64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips32r6" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64r6" == target."arch" or null)) || ("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null)))); + } + { + name = "errno"; + packageId = "errno"; + rename = "libc_errno"; + usesDefaultFeatures = false; + target = { target, features }: ((!(target."windows" or false)) && ((target."rustix_use_libc" or false) || (target."miri" or false) || (!(("linux" == target."os" or null) && ("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("riscv64" == target."arch" or null) || ((target."rustix_use_experimental_asm" or false) && ("powerpc64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips32r6" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64r6" == target."arch" or null)) || ("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null))))))); + } + { + name = "errno"; + packageId = "errno"; + rename = "libc_errno"; + usesDefaultFeatures = false; + target = { target, features }: (target."windows" or false); + } + { + name = "libc"; + packageId = "libc"; + optional = true; + usesDefaultFeatures = false; + target = { target, features }: ((!(target."rustix_use_libc" or false)) && (!(target."miri" or false)) && ("linux" == target."os" or null) && ("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("riscv64" == target."arch" or null) || ((target."rustix_use_experimental_asm" or false) && ("powerpc64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips32r6" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64r6" == target."arch" or null)) || ("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null)))); + features = [ "extra_traits" ]; + } + { + name = "libc"; + packageId = "libc"; + usesDefaultFeatures = false; + target = { target, features }: ((!(target."windows" or false)) && ((target."rustix_use_libc" or false) || (target."miri" or false) || (!(("linux" == target."os" or null) && ("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("riscv64" == target."arch" or null) || ((target."rustix_use_experimental_asm" or false) && ("powerpc64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips32r6" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64r6" == target."arch" or null)) || ("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null))))))); + features = [ "extra_traits" ]; + } + { + name = "linux-raw-sys"; + packageId = "linux-raw-sys 0.4.12"; + usesDefaultFeatures = false; + target = { target, features }: ((("android" == target."os" or null) || ("linux" == target."os" or null)) && ((target."rustix_use_libc" or false) || (target."miri" or false) || (!(("linux" == target."os" or null) && ("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("riscv64" == target."arch" or null) || ((target."rustix_use_experimental_asm" or false) && ("powerpc64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips32r6" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64r6" == target."arch" or null)) || ("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null))))))); + features = [ "general" "ioctl" "no_std" ]; + } + { + name = "linux-raw-sys"; + packageId = "linux-raw-sys 0.4.12"; + usesDefaultFeatures = false; + target = { target, features }: ((!(target."rustix_use_libc" or false)) && (!(target."miri" or false)) && ("linux" == target."os" or null) && ("little" == target."endian" or null) && (("arm" == target."arch" or null) || (("aarch64" == target."arch" or null) && ("64" == target."pointer_width" or null)) || ("riscv64" == target."arch" or null) || ((target."rustix_use_experimental_asm" or false) && ("powerpc64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips32r6" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64" == target."arch" or null)) || ((target."rustix_use_experimental_asm" or false) && ("mips64r6" == target."arch" or null)) || ("x86" == target."arch" or null) || (("x86_64" == target."arch" or null) && ("64" == target."pointer_width" or null)))); + features = [ "general" "errno" "ioctl" "no_std" "elf" ]; + } + { + name = "windows-sys"; + packageId = "windows-sys 0.48.0"; + target = { target, features }: (target."windows" or false); + features = [ "Win32_Foundation" "Win32_Networking_WinSock" "Win32_NetworkManagement_IpHelper" "Win32_System_Threading" ]; + } + ]; + devDependencies = [ + { + name = "errno"; + packageId = "errno"; + rename = "libc_errno"; + usesDefaultFeatures = false; + } + { + name = "libc"; + packageId = "libc"; + } + ]; + features = { + "all-apis" = [ "event" "fs" "io_uring" "mm" "mount" "net" "param" "pipe" "process" "procfs" "pty" "rand" "runtime" "shm" "stdio" "system" "termios" "thread" "time" ]; + "default" = [ "std" "use-libc-auxv" ]; + "io_uring" = [ "event" "fs" "net" "linux-raw-sys/io_uring" ]; + "itoa" = [ "dep:itoa" ]; + "libc" = [ "dep:libc" ]; + "libc_errno" = [ "dep:libc_errno" ]; + "linux_latest" = [ "linux_4_11" ]; + "net" = [ "linux-raw-sys/net" "linux-raw-sys/netlink" "linux-raw-sys/if_ether" ]; + "once_cell" = [ "dep:once_cell" ]; + "param" = [ "fs" ]; + "process" = [ "linux-raw-sys/prctl" ]; + "procfs" = [ "once_cell" "itoa" "fs" ]; + "pty" = [ "itoa" "fs" ]; + "runtime" = [ "linux-raw-sys/prctl" ]; + "rustc-dep-of-std" = [ "dep:core" "dep:alloc" "dep:compiler_builtins" "linux-raw-sys/rustc-dep-of-std" "bitflags/rustc-dep-of-std" "compiler_builtins?/rustc-dep-of-std" ]; + "shm" = [ "fs" ]; + "std" = [ "bitflags/std" "alloc" "libc?/std" "libc_errno?/std" ]; + "system" = [ "linux-raw-sys/system" ]; + "thread" = [ "linux-raw-sys/prctl" ]; + "use-libc" = [ "libc_errno" "libc" ]; + }; + resolvedDefaultFeatures = [ "alloc" "default" "fs" "std" "use-libc-auxv" ]; + }; "rustls" = rec { crateName = "rustls"; version = "0.21.7"; @@ -7878,9 +8016,9 @@ rec { }; "tempfile" = rec { crateName = "tempfile"; - version = "3.5.0"; + version = "3.8.1"; edition = "2018"; - sha256 = "163rp254r3x7i5hisagrpxid2166pq94jvk511dpkmc1yf2fryxr"; + sha256 = "1r88v07zdafzf46y63vs39rmzwl4vqd4g2c5qarz9mqa8nnavwby"; authors = [ "Steven Allen " "The Rust Project Developers" @@ -7898,18 +8036,18 @@ rec { } { name = "redox_syscall"; - packageId = "redox_syscall 0.3.5"; + packageId = "redox_syscall 0.4.1"; target = { target, features }: ("redox" == target."os" or null); } { name = "rustix"; - packageId = "rustix"; + packageId = "rustix 0.38.21"; target = { target, features }: ((target."unix" or false) || ("wasi" == target."os" or null)); features = [ "fs" ]; } { name = "windows-sys"; - packageId = "windows-sys 0.45.0"; + packageId = "windows-sys 0.48.0"; target = { target, features }: (target."windows" or false); features = [ "Win32_Storage_FileSystem" "Win32_Foundation" ]; } @@ -9849,6 +9987,10 @@ rec { name = "lazy_static"; packageId = "lazy_static"; } + { + name = "tempfile"; + packageId = "tempfile"; + } { name = "test-case"; packageId = "test-case"; diff --git a/tvix/glue/Cargo.toml b/tvix/glue/Cargo.toml index 90ad27526..b0902b5c9 100644 --- a/tvix/glue/Cargo.toml +++ b/tvix/glue/Cargo.toml @@ -20,6 +20,7 @@ git = "https://github.com/tvlfyi/wu-manber.git" [dev-dependencies] criterion = { version = "0.5", features = ["html_reports"] } lazy_static = "1.4.0" +tempfile = "3.8.1" test-case = "2.2.2" [[bench]] diff --git a/tvix/glue/src/tvix_store_io.rs b/tvix/glue/src/tvix_store_io.rs index 31a472fed..325e11e97 100644 --- a/tvix/glue/src/tvix_store_io.rs +++ b/tvix/glue/src/tvix_store_io.rs @@ -357,3 +357,93 @@ async fn import_path_with_pathinfo( Ok(path_info) } + +#[cfg(test)] +mod tests { + use std::{cell::RefCell, path::Path, rc::Rc, sync::Arc}; + + use tempfile::TempDir; + use tvix_castore::{blobservice::MemoryBlobService, directoryservice::MemoryDirectoryService}; + use tvix_eval::EvaluationResult; + use tvix_store::pathinfoservice::MemoryPathInfoService; + + use crate::{builtins::add_derivation_builtins, known_paths::KnownPaths}; + + use super::TvixStoreIO; + + /// evaluates a given nix expression and returns the result. + /// Takes care of setting up the evaluator so it knows about the + // `derivation` builtin. + fn eval(str: &str) -> EvaluationResult { + let mut eval = tvix_eval::Evaluation::new_impure(str, None); + + let blob_service = Arc::new(MemoryBlobService::default()); + let directory_service = Arc::new(MemoryDirectoryService::default()); + let path_info_service = Arc::new(MemoryPathInfoService::new( + blob_service.clone(), + directory_service.clone(), + )); + let runtime = tokio::runtime::Runtime::new().unwrap(); + + eval.io_handle = Box::new(TvixStoreIO::new( + blob_service, + directory_service, + path_info_service, + runtime.handle().clone(), + )); + + let known_paths: Rc> = Default::default(); + + add_derivation_builtins(&mut eval, known_paths.clone()); + + // run the evaluation itself. + eval.evaluate() + } + + /// Helper function that takes a &Path, and invokes a tvix evaluator coercing that path to a string + /// (via "${/this/path}"). The path can be both absolute or not. + /// It returns Option, depending on whether the evaluation succeeded or not. + fn import_path_and_compare>(p: P) -> Option { + // Try to import the path using "${/tmp/path/to/test}". + // The format string looks funny, the {} passed to Nix needs to be + // escaped. + let code = format!(r#""${{{}}}""#, p.as_ref().display()); + let result = eval(&code); + + if !result.errors.is_empty() { + return None; + } + + let value = result.value.expect("must be some"); + match value { + tvix_eval::Value::String(s) => return Some(s.as_str().to_owned()), + _ => panic!("unexpected value type: {:?}", value), + } + } + + /// Import a directory with a zero-sized ".keep" regular file. + /// Ensure it matches the (pre-recorded) store path that Nix would produce. + #[test] + fn import_directory() { + let tmpdir = TempDir::new().unwrap(); + + // create a directory named "test" + let src_path = tmpdir.path().join("test"); + std::fs::create_dir(&src_path).unwrap(); + + // write a regular file `.keep`. + std::fs::write(src_path.join(".keep"), vec![]).unwrap(); + + // importing the path with .../test at the end. + assert_eq!( + Some("/nix/store/gq3xcv4xrj4yr64dflyr38acbibv3rm9-test".to_string()), + import_path_and_compare(&src_path) + ); + + // importing the path with .../test/. at the end. + assert_eq!( + Some("/nix/store/gq3xcv4xrj4yr64dflyr38acbibv3rm9-test".to_string()), + import_path_and_compare(src_path.join(".")) + ); + } +}