about summary refs log tree commit diff
path: root/tvix/glue/src/tvix_store_io.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tvix/glue/src/tvix_store_io.rs')
-rw-r--r--tvix/glue/src/tvix_store_io.rs90
1 files changed, 90 insertions, 0 deletions
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("."))
+        );
+    }
+}