#![cfg(all(feature = "embed", feature = "test-support", feature = "unix-runtime"))]
use mxsh::ShellBuilder;
use mxsh::embed::DiagnosticCategory;
use mxsh::policy::ShellOptions;
use mxsh::runtime::testing::InMemoryRuntime;
#[test]
fn parse_diagnostics_include_category_code_source_and_range() {
let mut shell = ShellBuilder::new()
.new_session()
.expect("session should build");
let mut runtime = InMemoryRuntime::new();
let result = shell.run(&mut runtime, "if true; then\n");
assert_eq!(result.status, 2);
let parse = result
.diagnostics
.iter()
.find(|diagnostic| diagnostic.category == DiagnosticCategory::Input)
.expect("expected parse diagnostic");
assert_eq!(parse.code, "parse.syntax");
assert_eq!(parse.source.as_deref(), Some("mxsh"));
let range = parse.range.expect("parse diagnostic should carry a range");
assert_eq!(range.begin.line, 2);
assert!(parse.message.contains("fi"));
}
#[test]
fn resolve_diagnostics_are_tagged_with_resolution_metadata() {
let mut shell = ShellBuilder::new()
.new_session()
.expect("session should build");
let mut runtime = InMemoryRuntime::new();
let result = shell.run(&mut runtime, "definitely_missing_command");
assert_eq!(result.status, 127);
let resolution = result
.diagnostics
.iter()
.find(|diagnostic| diagnostic.category == DiagnosticCategory::CommandLookup)
.expect("expected resolve diagnostic");
assert_eq!(resolution.code, "resolve.not_found");
assert_eq!(resolution.source.as_deref(), Some("mxsh"));
let range = resolution
.range
.expect("resolution diagnostic should carry a line");
assert_eq!(range.begin.line, 1);
assert!(resolution.message.contains("command not found"));
}
#[test]
fn expansion_diagnostics_capture_nounset_failures() {
let mut options = ShellOptions::default();
options.insert(ShellOptions::NOUNSET);
let mut shell = ShellBuilder::new()
.options(options)
.new_session()
.expect("session should build");
let mut runtime = InMemoryRuntime::new();
let result = shell.run(&mut runtime, "echo $MISSING");
assert_eq!(result.exit_code, Some(1));
let expansion = result
.diagnostics
.iter()
.find(|diagnostic| diagnostic.category == DiagnosticCategory::Expansion)
.expect("expected expansion diagnostic");
assert_eq!(expansion.code, "expand.parameter_unset");
assert_eq!(expansion.source.as_deref(), Some("mxsh"));
assert!(expansion.message.contains("parameter not set"));
}
#[test]
fn expansion_diagnostics_capture_arithmetic_ranges() {
let mut shell = ShellBuilder::new()
.new_session()
.expect("session should build");
let mut runtime = InMemoryRuntime::new();
let result = shell.run(&mut runtime, "echo $((1 + 2x))");
assert_eq!(result.exit_code, Some(2));
let expansion = result
.diagnostics
.iter()
.find(|diagnostic| diagnostic.code == "expand.arithmetic")
.expect("expected arithmetic expansion diagnostic");
assert_eq!(expansion.category, DiagnosticCategory::Expansion);
assert_eq!(expansion.source.as_deref(), Some("mxsh"));
let range = expansion
.range
.expect("arithmetic diagnostic should carry a source range");
assert_eq!(range.begin.line, 1);
assert_eq!(range.begin.column, 6);
assert_eq!(range.end.line, 1);
assert!(range.end.column > range.begin.column);
}