use playground::opt::Opt; use rand::distributions::Alphanumeric; use rand::{thread_rng, Rng}; use std::env; use std::ffi::OsStr; use std::io::Result; use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; struct TestRuntime { scratch: PathBuf, } impl TestRuntime { fn new() -> Result { let scratch = Self::create_scratch_dir()?; Ok(TestRuntime { scratch }) } fn create_scratch_dir() -> Result { let tmp = env::temp_dir(); let scratch = tmp.join(Self::random_string()); if scratch.exists() { let _ = std::fs::remove_dir_all(&scratch); } std::fs::create_dir(&scratch)?; Ok(scratch) } fn random_string() -> String { format!( "playground-test.{}", thread_rng() .sample_iter(&Alphanumeric) .take(10) .collect::() ) } fn temp_dir>(&self, path: I) -> PathBuf { self.scratch.join(path) } fn run + std::fmt::Debug, S: AsRef + std::fmt::Debug>( &self, args: I, ) -> std::io::Result { let mut play = std::process::Command::new(playground_binary_path()); play.env("TMP", &self.scratch) .env("TMPDIR", &self.scratch) .args(args) .stderr(Stdio::piped()) .stdout(Stdio::piped()) .output() .map(From::from) } } impl Drop for TestRuntime { fn drop(&mut self) { let _ = std::fs::remove_dir_all(&self.scratch); } } fn playground_binary_path() -> PathBuf { let mut path = env::current_exe().unwrap(); path.pop(); if path.ends_with("deps") { path.pop(); } let exe = String::from("playground") + env::consts::EXE_SUFFIX; path.push(exe); path } #[derive(Debug)] struct StringOutput { pub status: ExitStatus, pub stdout: String, pub stderr: String, } impl From for StringOutput { fn from(v: Output) -> Self { StringOutput { status: v.status, stdout: String::from_utf8_lossy(&v.stdout).to_string(), stderr: String::from_utf8_lossy(&v.stderr).to_string(), } } } #[test] fn basic() -> Result<()> { let rt = TestRuntime::new()?; let output = rt.run(&["fixtures/hello.rs"])?; assert_eq!(output.status.code().unwrap(), 0); assert_eq!(output.stdout, "Hello World!\n"); Ok(()) } #[test] fn clean() -> Result<()> { let rt = TestRuntime::new()?; let opt = Opt::with_files(vec!["fixtures/hello.rs"]); let path = rt.temp_dir(opt.temp_dirname()); let canary = path.clone().join("canary"); if path.exists() { std::fs::remove_dir_all(&path)?; } println!("{:?}", path); let _ = rt.run(&["fixtures/hello.rs"])?; assert!(path.exists()); std::fs::write(&canary, "I_AM_CANARY")?; assert!(canary.exists()); let _ = rt.run(&["--clean", "fixtures/hello.rs"])?; assert!(!canary.exists()); Ok(()) } #[test] fn debug_mode() -> Result<()> { let rt = TestRuntime::new()?; let opt = Opt::with_files(vec!["fixtures/hello.rs"]); let path = rt.temp_dir(opt.temp_dirname()); let _ = rt.run(&["fixtures/hello.rs"])?; assert!(path.join("target").join("debug").exists()); assert!(!path.join("target").join("release").exists()); Ok(()) } #[test] fn release_mode() -> Result<()> { let rt = TestRuntime::new()?; let opt = Opt::with_files(vec!["fixtures/hello.rs"]); let path = rt.temp_dir(opt.temp_dirname()); let _ = rt.run(&["--release", "fixtures/hello.rs"])?; assert!(!path.join("target").join("debug").exists()); assert!(path.join("target").join("release").exists()); Ok(()) } #[test] fn cargo_option() -> Result<()> { let rt = TestRuntime::new()?; let opt = Opt::with_files(vec!["fixtures/hello.rs"]); let path = rt.temp_dir(opt.temp_dirname()); let _ = rt.run(&["--cargo-option=--release", "fixtures/hello.rs"])?; assert!(!path.join("target").join("debug").exists()); assert!(path.join("target").join("release").exists()); Ok(()) } #[test] fn program_args() -> Result<()> { let rt = TestRuntime::new()?; let output = rt.run(&["fixtures/args.rs", "--", "test"])?; assert_eq!(output.stdout, "test\n"); Ok(()) } #[test] fn external_crate() -> Result<()> { let rt = TestRuntime::new()?; let output = rt.run(&["fixtures/bitflags.rs"])?; assert_eq!(output.status.code().unwrap(), 0); Ok(()) } #[test] fn simple_infer() -> Result<()> { let rt = TestRuntime::new()?; let output = rt.run(&["--infer", "fixtures/infer.rs"])?; assert_eq!(output.status.code().unwrap(), 0); Ok(()) } #[test] fn infer_failure() -> Result<()> { let rt = TestRuntime::new()?; let output = rt.run(&["--infer", "fixtures/infer-failure.rs"])?; assert_ne!(output.status.code().unwrap(), 0); Ok(()) } #[test] fn infer_override() -> Result<()> { let rt = TestRuntime::new()?; let output = rt.run(&["--infer", "fixtures/infer-override.rs"])?; assert_eq!(output.status.code().unwrap(), 0); Ok(()) } #[test] fn dtoa_test() -> Result<()> { let rt = TestRuntime::new()?; let output = rt.run(&["fixtures/dtoa.rs"])?; assert_eq!(output.status.code().unwrap(), 0); Ok(()) } #[test] fn serde_test() -> Result<()> { let rt = TestRuntime::new()?; let output = rt.run(&["fixtures/serde.rs"])?; assert_eq!(output.status.code().unwrap(), 0); Ok(()) } #[test] fn multi_test() -> Result<()> { let rt = TestRuntime::new()?; let output = rt.run(&["fixtures/multi/entry.rs", "fixtures/multi/hello.rs"])?; assert_eq!(output.status.code().unwrap(), 0); Ok(()) } #[test] fn subdirs_test() -> Result<()> { let rt = TestRuntime::new()?; let output = rt.run(&["fixtures/subdirs/hello.rs", "fixtures/subdirs/World.rs"])?; assert_eq!(output.status.code().unwrap(), 0); Ok(()) } #[test] fn version_test() -> Result<()> { let rt = TestRuntime::new()?; let output = rt.run(&["fixtures/version/version.rs"])?; assert_eq!(output.status.code().unwrap(), 0); Ok(()) }