use std::path::PathBuf;
use falcon_mdf::{ChannelGroup, Mf4File};
const PATHS: [&str; 2] = [
"test_data/reference/single_lin_bus_1.MF4",
"test_data/reference/multiple.MF4",
];
fn resolve_path(rel: &str) -> Option<PathBuf> {
let candidates = [
PathBuf::from(rel),
PathBuf::from("../../falcon_mdf").join(rel),
];
candidates.into_iter().find(|p| p.exists())
}
fn present_paths() -> Vec<String> {
PATHS
.into_iter()
.filter_map(|p| resolve_path(p).map(|pb| pb.to_string_lossy().to_string()))
.collect()
}
fn skip_if_empty(paths: &[String]) -> bool {
if paths.is_empty() {
eprintln!("SKIP: no LIN reference files present under test_data/reference/");
return true;
}
false
}
fn lin_groups(file: &Mf4File) -> Vec<&ChannelGroup> {
file.data_groups()
.iter()
.flat_map(|dg| dg.channel_groups.iter())
.filter(|cg| {
cg.find_channel("LIN_Frame.ID").is_some()
&& cg.find_channel("LIN_Frame.DataBytes").is_some()
})
.collect()
}
#[test]
fn frame_count_matches_the_group_sample_count() {
let paths = present_paths();
if skip_if_empty(&paths) {
return;
}
let mut checked = 0usize;
for path in &paths {
let file = Mf4File::open(path).unwrap_or_else(|e| panic!("{path}: {e}"));
for group in lin_groups(&file) {
let frames = file
.lin_frames(group)
.unwrap_or_else(|e| panic!("{path} group {}: {e}", group.index));
assert_eq!(
frames.len() as u64,
group.sample_count,
"{path} group '{}': frame count",
group.acquisition_name
);
checked += 1;
}
}
assert!(checked > 0, "no LIN frame group was found in the corpus");
eprintln!("checked {checked} LIN frame group(s)");
}
#[test]
fn frames_are_in_logging_order() {
let paths = present_paths();
if skip_if_empty(&paths) {
return;
}
for path in &paths {
let file = Mf4File::open(path).unwrap();
for group in lin_groups(&file) {
let mut previous = f64::NEG_INFINITY;
for (i, frame) in file.lin_frames(group).unwrap().iter().enumerate() {
assert!(
frame.timestamp >= previous,
"{path} group {} frame {i}: timestamp {} precedes {previous}",
group.index,
frame.timestamp
);
previous = frame.timestamp;
}
}
}
}
#[test]
fn identifiers_are_six_bits() {
let paths = present_paths();
if skip_if_empty(&paths) {
return;
}
let mut frames_seen = 0usize;
for path in &paths {
let file = Mf4File::open(path).unwrap();
for group in lin_groups(&file) {
for (i, frame) in file.lin_frames(group).unwrap().iter().enumerate() {
frames_seen += 1;
assert!(
frame.id <= 63,
"{path} group {} frame {i}: identifier {:#X} exceeds 6 bits",
group.index,
frame.id
);
}
}
}
assert!(frames_seen > 0, "no LIN frame was read from the corpus");
}
#[test]
fn payloads_are_trimmed_to_the_logged_length() {
let paths = present_paths();
if skip_if_empty(&paths) {
return;
}
for path in &paths {
let file = Mf4File::open(path).unwrap();
for group in lin_groups(&file) {
let length_channel = group
.find_channel("LIN_Frame.DataLength")
.expect("a LIN frame group has a DataLength channel");
let lengths = file
.signal(length_channel)
.unwrap()
.values()
.unwrap()
.to_f64();
let frames = file.lin_frames(group).unwrap();
for (i, frame) in frames.iter().enumerate() {
assert_eq!(
frame.data.len() as f64,
lengths[i],
"{path} group {} frame {i}: payload length",
group.index
);
}
}
}
}