Lines
100 %
Functions
Branches
// Skipped under Miri: spawns the built nms binary (which runs wasm via
// wasmtime); subprocess execution and Cranelift can't run under Miri.
#![cfg(not(miri))]
//! Smoke tests for the `nms --test PATH` subcommand. Invokes the
//! built binary so the runner's argv/exit-code contract is what CI
//! actually checks: a non-zero exit code is the only signal an
//! external harness sees when a deftest fails.
use std::path::PathBuf;
use std::process::Command;
fn nms_bin() -> PathBuf {
// CARGO_BIN_EXE_<name> is set by cargo when building integration
// tests for a crate with a `[[bin]]` of that name. Reliable across
// workspace + isolated layouts; no manual target-dir parsing.
PathBuf::from(env!("CARGO_BIN_EXE_nms"))
}
fn samples_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.parent()
.unwrap()
.join("nomiscript/tests/nms_runner_samples")
#[test]
fn test_subcommand_runs_all_files_in_dir() {
let out = Command::new(nms_bin())
.arg("--test")
.arg(samples_dir())
.output()
.expect("invoke nms");
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
assert!(
out.status.success(),
"expected success, got {:?}\nstdout: {stdout}\nstderr: {stderr}",
out.status
);
assert!(stdout.contains("0 failed"), "stdout: {stdout}");
fn test_subcommand_accepts_single_file() {
let path = samples_dir().join("arithmetic.nms");
.arg(&path)
assert!(out.status.success(), "stderr: {:?}", out.stderr);
assert!(stdout.contains("5 passed"), "stdout: {stdout}");
fn test_subcommand_nonzero_exit_on_failure() {
let dir = tempfile_dir("nms_runner_failure_");
std::fs::write(
dir.join("a.nms"),
"(deftest will-fail (assert-equal 1 2))\n",
)
.unwrap();
.arg(&dir)
assert!(!out.status.success(), "expected non-zero exit on failure");
assert!(stdout.contains("1 failed"), "stdout: {stdout}");
fn coverage_flag_appends_coverage_section() {
.arg("--coverage")
assert!(stdout.contains("--- coverage ---"), "stdout: {stdout}");
// sandbox nms has no host fns registered, so the dump is the
// explanatory placeholder rather than a native-fn list. The rpc
// crate's unit tests assert the populated path.
stdout.contains("(no native fns referenced)"),
"stdout: {stdout}"
fn invalid_profile_strategy_errors_with_clear_message() {
.arg("--profile=bogus")
.arg("-e")
.arg("(+ 1 2)")
assert!(!out.status.success(), "expected non-zero exit");
stderr.contains("unknown --profile strategy"),
"stderr: {stderr}"
fn perfmap_profile_strategy_accepted() {
// PerfMap is the lighter Linux profiler agent. We don't validate
// the output file (path depends on PID); just confirm the flag is
// accepted and the eval completes.
.arg("--profile=perfmap")
.arg("(+ 2 2)")
assert!(stdout.contains('4'), "stdout: {stdout}");
fn test_subcommand_errors_on_empty_dir() {
let dir = tempfile_dir("nms_runner_empty_");
assert!(!out.status.success(), "expected non-zero exit on empty dir");
fn tempfile_dir(prefix: &str) -> PathBuf {
let dir = std::env::temp_dir().join(format!(
"{prefix}{}",
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.as_nanos()
));
std::fs::create_dir_all(&dir).unwrap();
dir