RustedSciThe 0.4.16

Rust framework for symbolic and numerical computing:BVP ( Newton-Raphson frozen/damped/with collocations ), IVP( BDF, Radau, Backward Euler, LSODE, LSODA, RK45, DoPri), nonlinear equations ( Levenberg, Gavin) and more
Documentation
//! Task shell CLI contract tests.
//!
//! Copy-paste commands:
//! `cargo test --test task_shell_cli_contract -- --nocapture --test-threads=1`
//! `cargo test --test task_shell_cli_contract help_mentions_current_top_level_commands -- --nocapture --test-threads=1`
//! `cargo test --test task_shell_cli_contract showcase_mentions_parser_ready_template_and_guide_entrypoints -- --nocapture --test-threads=1`
//! `cargo test --test task_shell_cli_contract check_mode_renders_substituted_preview_without_running_solver -- --nocapture --test-threads=1`
//! `cargo test --test task_shell_cli_contract ffi_dependency_report_lists_expected_tools -- --nocapture --test-threads=1`

use std::fs;
use std::path::PathBuf;
use std::process::Command;
use tempfile::tempdir;

fn rustedscithe_bin() -> PathBuf {
    std::env::var_os("CARGO_BIN_EXE_RustedSciThe")
        .or_else(|| std::env::var_os("CARGO_BIN_EXE_rustedscithe"))
        .map(PathBuf::from)
        .expect("RustedSciThe binary should be available to integration tests")
}

fn run_cli(args: &[&str]) -> std::process::Output {
    Command::new(rustedscithe_bin())
        .args(args)
        .output()
        .expect("CLI process should start")
}

fn read_fixture(name: &str) -> String {
    fs::read_to_string(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures").join(name))
        .expect("fixture should be readable")
}

fn write_temp_task_doc(contents: &str, stem: &str) -> PathBuf {
    let dir = tempdir().expect("tempdir should be created");
    let dir_path = dir.keep();
    let path = dir_path.join(format!("{stem}.txt"));
    fs::write(&path, contents).expect("task document should be writable");
    path
}

#[test]
fn help_mentions_current_top_level_commands() {
    let output = run_cli(&["--help"]);
    assert!(output.status.success(), "help command should succeed");
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert_eq!(stdout, read_fixture("task_shell_help.txt"));
}

#[test]
fn showcase_mentions_parser_ready_template_and_guide_entrypoints() {
    let output = run_cli(&["showcase"]);
    assert!(output.status.success(), "showcase command should succeed");
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert_eq!(stdout, read_fixture("task_shell_showcase.txt"));
}

#[test]
fn check_mode_renders_substituted_preview_without_running_solver() {
    let task_doc = r#"
task
solver: IVP
method: RK45

equations
arg: t
y: -y

initial_conditions
t0: 0.0
t_end: 1.0
y0: 1.0

solver_options
step_size: 1e-3
"#;
    let path = write_temp_task_doc(task_doc, "ivp_check_contract");
    let output = run_cli(&["check", path.to_string_lossy().as_ref()]);

    assert!(output.status.success(), "check mode should succeed");
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(stdout.contains("[Task check] IVP"));
    assert!(stdout.contains("fully substituted equations"));
    assert!(stdout.contains("solver=IVP, method=RK45"));
    assert!(stdout.contains("idx | unknown | rhs"));
    assert!(stdout.contains("0 | y | -1 * y"));
}

#[test]
fn ffi_dependency_report_lists_expected_tools() {
    let output = run_cli(&["check-ffi-dependencies"]);
    assert!(output.status.success(), "ffi dependency probe should succeed");
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(stdout.contains("RustedSciThe external dependency report"));
    assert!(stdout.contains("platform:"));
    assert!(stdout.contains("probe strategy: PATH-based process checks"));
    assert!(stdout.contains("rustc"));
    assert!(stdout.contains("cargo"));
    assert!(stdout.contains("tcc"));
    assert!(stdout.contains("gcc"));
    assert!(stdout.contains("zig"));
    assert!(stdout.contains("gnuplot"));
    assert!(stdout.contains("pandoc"));
    assert!(stdout.contains("arrayfire"));
}