about summary refs log tree commit diff
path: root/tvix/glue
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2023-12-13T09·34+0200
committerflokli <flokli@flokli.de>2023-12-13T13·41+0000
commit3cdde8ad5a4650cbb248b070891daf72ccfc9af0 (patch)
tree5dcf095995373cc5ca64c6becdc52ff333512bf7 /tvix/glue
parent8b614809359439694d47d1804fff1a0bb44827bf (diff)
feat(tvix/glue): add some import tests r/7212
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 <flokli@flokli.de>
Reviewed-by: raitobezarius <tvl@lahfa.xyz>
Diffstat (limited to 'tvix/glue')
-rw-r--r--tvix/glue/Cargo.toml1
-rw-r--r--tvix/glue/src/tvix_store_io.rs90
2 files changed, 91 insertions, 0 deletions
diff --git a/tvix/glue/Cargo.toml b/tvix/glue/Cargo.toml
index 90ad2752691d..b0902b5c9983 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 31a472fed21c..325e11e97397 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<RefCell<KnownPaths>> = 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<String>, depending on whether the evaluation succeeded or not.
+    fn import_path_and_compare<P: AsRef<Path>>(p: P) -> Option<String> {
+        // 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("."))
+        );
+    }
+}