//! `flowrsc can-node`: a DBC file in, the CAN→ROS 2 node's project out, each topic named with //! its type's FIH01 hash, and what ROS cannot carry said on stderr. use std::path::Path; use clap::Parser; use flowrs_cli::{Cli, EXIT_OK, EXIT_USAGE, run}; fn flowrsc(args: &[&str]) -> (i32, String, String) { let cli = Cli::parse_from(std::iter::once("flowrsc").chain(args.iter().copied())); let (mut out, mut err) = (Vec::new(), Vec::new()); let code = run(&cli, &mut out, &mut err); ( code, String::from_utf8(out).unwrap(), String::from_utf8(err).unwrap(), ) } #[test] fn can_node_writes_the_project_and_names_each_topic_with_its_fih01() { let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../.."); let dbc = root.join("crates/flowrs-iface/fixtures/can/vehicle.dbc"); let dir = tempfile::tempdir().unwrap(); let (code, out, err) = flowrsc(&[ "can-node", dbc.to_str().unwrap(), "-o", dir.path().to_str().unwrap(), "--flowrs", root.to_str().unwrap(), ]); assert_eq!(code, EXIT_OK, "{err}"); let first = out.lines().next().unwrap(); assert!( first.starts_with("/vehicle/wheel_speeds\tvehicle/msg/WheelSpeeds\t0x1A0\tFIH01_"), "{out}" ); assert!(out.contains("0x18FEF100 (29-bit)"), "{out}"); assert_eq!(out.lines().count(), 6); assert!( err.contains("not carried: vehicle/msg/DiagMux.BusVoltage"), "{err}" ); let msg = std::fs::read_to_string(dir.path().join("ros/vehicle/msg/WheelSpeeds.msg")).unwrap(); assert!(msg.contains("float64 speed_fl # [km/h]"), "{msg}"); for f in [ "Cargo.toml", "src/main.rs", ".cargo/config.toml", "ros/vehicle/package.xml", ] { assert!(dir.path().join(f).is_file(), "{f}"); } let (code, _, err) = flowrsc(&[ "can-node", dbc.to_str().unwrap(), "-o", dir.path().to_str().unwrap(), "--flowrs", root.to_str().unwrap(), "--distro", "iron", ]); assert_eq!(code, EXIT_USAGE, "{err}"); }