//! A program a test writes and then runs, written by a process other than the test's own. //! //! A file that is open for writing anywhere cannot be run: on Linux exec fails with ETXTBSY //! ("Text file busy", os error 26). A fork copies every open descriptor of the process that //! forks into its child, which holds them until it runs its own program. So a program file a //! test writes itself can still be open for writing, in the child of a spawn that another test's //! thread makes in that moment, when the test, or the `wai` it starts, runs it. Renaming the file //! into place changes nothing: the child holds the same file. Here `sh` writes it, or `cp` //! copies it, and has exited before these return: no descriptor for it is ever in the test's //! process, and none is left anywhere when it runs. //! //! The integration tests include this file (`#[path = "support/program.rs"]`), and so do the //! unit tests of the `wai` binary (`src/bin/wai.rs`): every test of this crate that runs a //! program it made makes it here. #![allow(dead_code)] use std::path::Path; /// `text`, exactly, at `path`, with mode 755: written by `sh`. #[cfg(unix)] pub fn write_program(path: &Path, text: &str) { let status = std::process::Command::new("/bin/sh") .args(["-c", r#"printf %s "$2" > "$1" && chmod 755 "$1""#, "sh"]) .arg(path) .arg(text) .status() .expect("/bin/sh runs"); assert!(status.success(), "{} was not written", path.display()); } /// A copy of the program `from` at `to`: made by `cp` on Unix, and by this process elsewhere, /// where no such error exists. pub fn copy_program(from: &Path, to: &Path) { #[cfg(unix)] { let status = std::process::Command::new("/bin/cp").arg(from).arg(to).status().expect("/bin/cp runs"); assert!(status.success(), "{} was not copied to {}", from.display(), to.display()); } #[cfg(not(unix))] std::fs::copy(from, to).unwrap_or_else(|e| panic!("{} was not copied to {}: {e}", from.display(), to.display())); }