use crate::commands::SimCommand;
use crate::context::CliContext;
use crate::sim;
use anyhow::Result;
pub async fn handle_sim(_ctx: &mut CliContext, command: &SimCommand) -> Result<()> {
match command {
SimCommand::Generate(args) => {
println!();
println!("🤖 Generating MuJoCo MJCF");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
sim::generate(args).await?;
println!();
println!("✅ Wrote MJCF to {}", args.out.display());
Ok(())
}
SimCommand::Run(args) => {
println!();
println!("🤖 Running MuJoCo rollout");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
println!();
sim::run(args).await?;
println!();
println!("✅ Ran {} steps", args.steps);
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::commands::{SimBackend, SimGenerateArgs, SimRunArgs};
use crate::context::CliContextBuilder;
use std::path::PathBuf;
use tempfile::tempdir;
fn test_ctx() -> (tempfile::TempDir, CliContext) {
let dir = tempdir().unwrap();
let ctx = CliContextBuilder::new()
.working_dir(dir.path().to_path_buf())
.build()
.unwrap();
(dir, ctx)
}
#[tokio::test]
async fn handle_sim_generate_propagates_backend_error() {
let Ok(_) = std::process::Command::new("python3").arg("--version").output() else {
eprintln!("skipping: no python3 on PATH in this environment");
return;
};
let (_dir, mut ctx) = test_ctx();
let command = SimCommand::Generate(SimGenerateArgs {
backend: SimBackend::Mujoco,
model: "rover".to_string(),
env: None,
out: PathBuf::from("/tmp/mecha10-handle-sim-test-generate.xml"),
assets_path: None,
});
let Err(err) = handle_sim(&mut ctx, &command).await else {
panic!(
"expected handle_sim to propagate a backend error in this environment \
(mecha10_rl not installed) rather than report success"
);
};
let message = err.chain().map(ToString::to_string).collect::<Vec<_>>().join(": ");
assert!(
message.contains("MuJoCo backend not available") || message.contains("mecha10_rl.mujoco.cli exited with"),
"expected the underlying backend error to survive handle_sim unchanged, got: {message}"
);
}
#[tokio::test]
async fn handle_sim_run_propagates_backend_error() {
let Ok(_) = std::process::Command::new("python3").arg("--version").output() else {
eprintln!("skipping: no python3 on PATH in this environment");
return;
};
let (_dir, mut ctx) = test_ctx();
let command = SimCommand::Run(SimRunArgs {
backend: SimBackend::Mujoco,
model: "rover".to_string(),
env: "basic_arena".to_string(),
steps: 10,
assets_path: None,
});
let Err(err) = handle_sim(&mut ctx, &command).await else {
panic!(
"expected handle_sim to propagate a backend error in this environment \
(mecha10_rl not installed) rather than report success"
);
};
let message = err.chain().map(ToString::to_string).collect::<Vec<_>>().join(": ");
assert!(
message.contains("MuJoCo backend not available") || message.contains("mecha10_rl.mujoco.cli exited with"),
"expected the underlying backend error to survive handle_sim unchanged, got: {message}"
);
}
}