//! P1 integration: a read-only bundle and real shell calls from the durable harness. use sausage::{harness::run_module, world::World}; use sausage_vfs::Open; use std::path::PathBuf; #[tokio::test(flavor = "current_thread")] async fn bundle_mount_and_real_shell() -> anyhow::Result<()> { let repo = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(".."); let bundle = repo.join("target/userland/bin"); if !bundle.join("sh").exists() { assert!( std::process::Command::new("nu") .env_remove("CARGO_TARGET_DIR") .arg(repo.join("userland/bundle.nu")) .status()? .success() ); } let dir = tempfile::tempdir()?; let world = World::open_with_userland(dir.path(), Some(&bundle))?; assert!(world.root.stat("/bin/sh", true).await?.size > 0); assert!(world.root.stat("/usr/local/bin", true).await?.directory); let denied = world .root .open( "/bin/forbidden", Open { write: true, create: true, ..Default::default() }, ) .await; assert!(matches!(denied, Err(e) if e.kind() == std::io::ErrorKind::ReadOnlyFilesystem)); let exec = sausage::process::exec(World { root: world.root.clone(), host_dir: world.host_dir.clone(), processes: world.processes.clone(), })?; let source = format!( "globalThis.testP1 = true;\n{}", include_str!("../js/test-bundle.js") ); run_module(world, exec, &source).await?; assert_eq!( std::fs::read_to_string(dir.path().join("world/test.txt"))?, "after\n" ); assert_eq!( std::fs::read_to_string(dir.path().join("world/parallel/a"))?, "a" ); assert_eq!( std::fs::read_to_string(dir.path().join("world/parallel/b"))?, "b" ); let spills = std::fs::read_dir(dir.path().join("world/tmp"))?.collect::, _>>()?; assert_eq!(spills.len(), 1); let actual = std::fs::read_to_string(spills[0].path())?; let expected: String = (1..=10000).map(|n| format!("{n}\n")).collect(); assert_eq!(actual, expected); // An unbundled world remains usable by process tests and file-only callers. let unbundled = tempfile::tempdir()?; let world = World::open(unbundled.path())?; assert!(world.root.stat("/bin/sh", true).await.is_err()); Ok(()) }