//! Focused tests for source discovery, argument forwarding, eviction, and process cancellation. use super::*; #[tokio::test] async fn discovers_workspace_and_skips_target() -> Result<()> { let temp = tempfile::tempdir()?; let world = crate::world::World::open(temp.path())?; files::write( world.root.as_ref(), "/project/Cargo.toml", b"[workspace]\nmembers=['member']".to_vec(), ) .await?; files::write( world.root.as_ref(), "/project/member/Cargo.toml", b"[package]\nname='member'\nversion='0.1.0'".to_vec(), ) .await?; files::write( world.root.as_ref(), "/project/target/junk", b"junk".to_vec(), ) .await?; assert_eq!( files::workspace(world.root.as_ref(), "/project/member/src").await?, "/project" ); let copy = temp.path().join("copy"); files::copy_out(world.root.as_ref(), "/project", ©).await?; assert!(copy.join("member/Cargo.toml").exists()); assert!(!copy.join("target").exists()); Ok(()) } #[tokio::test] async fn clean_removes_only_deleted_artifacts() -> Result<()> { let temp = tempfile::tempdir()?; let world = crate::world::World::open(temp.path())?; let native = temp.path().join("native"); std::fs::create_dir_all(&native)?; std::fs::write(native.join("keep.wasm"), b"keep")?; for name in ["keep.wasm", "remove.wasm", "note.txt"] { files::write( world.root.as_ref(), &format!("/target/{name}"), b"data".to_vec(), ) .await?; } files::clean_artifacts(world.root.as_ref(), &native, "/target").await?; assert!( files::read(world.root.as_ref(), "/target/remove.wasm") .await .is_err() ); for name in ["keep.wasm", "note.txt"] { assert_eq!( files::read(world.root.as_ref(), &format!("/target/{name}")).await?, b"data" ); } Ok(()) } #[test] fn relative_host_directory_uses_absolute_namespace_paths() -> Result<()> { let temp = tempfile::tempdir()?; let world = crate::world::World::open(temp.path())?; let builder = Builder::new(world.root, Path::new("."))?; assert!(builder.directory.is_absolute()); Ok(()) } #[test] fn test_filter_is_not_a_build_argument() { let args = ["test", "-p", "example", "filter", "--release"].map(str::to_string); assert_eq!( test_build_args(&args), ["test", "-p", "example", "--release"] ); } #[test] fn disk_cap_removes_workspaces() -> Result<()> { let temp = tempfile::tempdir()?; let world = crate::world::World::open(temp.path())?; let builder = Builder::new(world.root, &world.host_dir)?; for name in ["a", "b"] { let path = builder.directory.join(name); std::fs::create_dir_all(&path)?; std::fs::write(path.join("last-used"), [])?; std::fs::write(path.join("data"), [0; 32])?; } std::fs::File::open(builder.directory.join("a/last-used"))? .set_times(std::fs::FileTimes::new().set_modified(std::time::UNIX_EPOCH))?; builder.evict(32)?; assert!(!builder.directory.join("a").exists()); assert!(builder.directory.join("b").exists()); assert_eq!(files::size(&builder.directory)?, 32); Ok(()) } #[tokio::test] async fn closed_receiver_cancels_command() -> Result<()> { let (tx, mut rx) = mpsc::channel(1); let mut cmd = Command::new("sh"); cmd.args(["-c", "printf ready; exec sleep 1000"]); let task = tokio::spawn(async move { run(cmd, &tx, Instant::now() + Duration::from_secs(60)).await }); // Output must arrive before the command exits, not after collection completes. let event = tokio::time::timeout(Duration::from_secs(2), rx.recv()) .await? .context("missing streamed output")?; assert!(matches!(event, Event::Stdout { bytes } if bytes == b"ready")); drop(rx); assert!( tokio::time::timeout(Duration::from_secs(2), task) .await?? .is_err() ); Ok(()) }