use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use re_chunk::{Chunk, EntityPath};
use crate::importer_mcap::McapImporter;
use crate::{ImportedData, Importer as _, ImporterSettings};
pub fn test_asset(name: &str) -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("src/importer_mcap/tests/assets")
.join(name)
}
struct McapTest {
mcap_file: &'static str,
entity_path: &'static str,
}
pub struct McapTestHarness {
tests: Vec<McapTest>,
}
impl McapTestHarness {
pub fn new() -> Self {
Self { tests: Vec::new() }
}
pub fn add(mut self, mcap_file: &'static str, entity_path: &'static str) -> Self {
self.tests.push(McapTest {
mcap_file,
entity_path,
});
self
}
pub fn run(self) {
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("snapshots");
settings.set_prepend_module_to_snapshot(false);
settings.bind(|| {
let mut tests_by_mcap = BTreeMap::<_, Vec<_>>::new();
for test in self.tests {
tests_by_mcap.entry(test.mcap_file).or_default().push(test);
}
for (mcap_file, tests) in tests_by_mcap {
let asset_path = test_asset(mcap_file);
let loaded_mcap = load_mcap(&asset_path);
let snapshot_name = Path::new(mcap_file)
.file_stem()
.and_then(|stem| stem.to_str())
.expect("MCAP test assets must have a UTF-8 file stem");
let snapshot = tests
.into_iter()
.map(|test| {
let chunks = loaded_mcap.chunks_for_entity(test.entity_path);
let chunk = chunks.get(1).unwrap_or_else(|| {
panic!(
"Expected a metadata chunk followed by a payload chunk at entity {}\nFile path: {}",
test.entity_path,
asset_path.display(),
)
});
format!("{chunk:-240}")
})
.collect::<Vec<_>>()
.join("\n\n");
let mut snapshot_settings = insta::Settings::clone_current();
snapshot_settings.set_input_file(&asset_path);
snapshot_settings.bind(|| {
insta::assert_snapshot!(snapshot_name, snapshot);
});
}
});
}
}
fn load_mcap(path: impl AsRef<Path>) -> LoadedMcap {
let path = path.as_ref();
let importer = McapImporter::default();
let (tx, rx) = crossbeam::channel::bounded(1024);
let settings = ImporterSettings::recommended("test");
importer
.import_from_path(&settings, path.to_path_buf(), tx)
.unwrap_or_else(|err| {
panic!("Failed to load MCAP file at {}: {err}", path.display());
});
let chunks: Vec<Chunk> = rx.iter().filter_map(ImportedData::into_chunk).collect();
LoadedMcap { chunks }
}
struct LoadedMcap {
chunks: Vec<Chunk>,
}
impl LoadedMcap {
fn chunks_for_entity(&self, path: &str) -> Vec<&Chunk> {
let entity_path: EntityPath = path.into();
self.chunks
.iter()
.filter(|c| c.entity_path() == &entity_path)
.collect()
}
}