use std::{ env, path::{Path, PathBuf}, process::{Command, Output}, }; #[test] #[ignore = "runs cargo build and target/debug/glagol; promotion smoke for the built CLI artifact"] fn cargo_build_produces_direct_binary_that_runs_supported_modes() { let manifest = Path::new(env!("CARGO_MANIFEST_DIR")); let build = Command::new("cargo") .arg("build") .current_dir(manifest) .output() .unwrap_or_else(|err| panic!("run cargo build: {}", err)); assert_success("cargo build", build); let binary = direct_debug_binary(manifest); assert!( binary.is_file(), "cargo build did not produce direct binary `{}`", binary.display() ); let add_fixture = manifest.join("../examples/add.slo"); let llvm = Command::new(&binary) .arg(&add_fixture) .output() .unwrap_or_else(|err| panic!("run `{}`: {}", binary.display(), err)); assert_success_contains( "direct binary LLVM emission", llvm, &[ "define i32 @add", "define i32 @main", "call void @print_i32", ], ); let test_fixture = manifest.join("../tests/top-level-test.slo"); let check_tests = Command::new(&binary) .arg("--check-tests") .arg(&test_fixture) .output() .unwrap_or_else(|err| panic!("run `{}` --check-tests: {}", binary.display(), err)); assert_success_stdout( "direct binary check-tests", check_tests, "test \"add works\" ... checked\n1 test(s) checked\n", ); let run_tests = Command::new(&binary) .arg("--run-tests") .arg(&test_fixture) .output() .unwrap_or_else(|err| panic!("run `{}` --run-tests: {}", binary.display(), err)); assert_success_stdout( "direct binary run-tests", run_tests, "test \"add works\" ... ok\n1 test(s) passed\n", ); } fn direct_debug_binary(manifest: &Path) -> PathBuf { let target = if let Some(target_dir) = env::var_os("CARGO_TARGET_DIR") { let target_dir = PathBuf::from(target_dir); if target_dir.is_absolute() { target_dir } else { manifest.join(target_dir) } } else { manifest.join("target") }; target.join("debug").join(binary_name()) } fn binary_name() -> String { format!("glagol{}", env::consts::EXE_SUFFIX) } fn assert_success(context: &str, output: Output) { let stdout = String::from_utf8_lossy(&output.stdout); let stderr = String::from_utf8_lossy(&output.stderr); assert!( output.status.success(), "{} failed\nstdout:\n{}\nstderr:\n{}", context, stdout, stderr ); } fn assert_success_contains(context: &str, output: Output, expected: &[&str]) { let stdout = String::from_utf8_lossy(&output.stdout); let stderr = String::from_utf8_lossy(&output.stderr); assert!( output.status.success(), "{} failed\nstdout:\n{}\nstderr:\n{}", context, stdout, stderr ); assert!(stderr.is_empty(), "{} wrote stderr:\n{}", context, stderr); for needle in expected { assert!( stdout.contains(needle), "{} stdout did not contain `{}`\nstdout:\n{}", context, needle, stdout ); } } fn assert_success_stdout(context: &str, output: Output, expected: &str) { let stdout = String::from_utf8_lossy(&output.stdout); let stderr = String::from_utf8_lossy(&output.stderr); assert!( output.status.success(), "{} failed\nstdout:\n{}\nstderr:\n{}", context, stdout, stderr ); assert_eq!(stdout, expected, "{} stdout mismatch", context); assert!(stderr.is_empty(), "{} wrote stderr:\n{}", context, stderr); }