Merge branch 'feat/p2-writer-groups-links' into feat/p2-perf-coverage
# Conflicts: # CHANGELOG.md # crates/clawhdf5-tools/tests/h5rs_interop.rs
This commit is contained in:
@@ -908,3 +908,119 @@ fn check_data_flags_mis_sized_vl_heap_objects() {
|
||||
assert!(s.contains("undefined global heap address"), "bad{tag}: {s}");
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// files clawhdf5 writes: nested groups and links
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Nested groups (4 levels, by builders and by path names), soft, hard and
|
||||
/// external links, creation-order tracking, and dense link and attribute
|
||||
/// storage, as `FileBuilder` writes them.
|
||||
fn write_nested_links(dir: &Path) -> Vec<String> {
|
||||
use clawhdf5::{AttrValue, FileBuilder};
|
||||
let mut b = FileBuilder::new();
|
||||
b.set_attr("title", AttrValue::String("links".into()));
|
||||
b.create_dataset("x/y").with_f64_data(&[1.0, 2.0]);
|
||||
b.create_dataset("a/b/c/d/leaf")
|
||||
.with_i32_data(&[4, 5])
|
||||
.set_attr("depth", AttrValue::I64(5));
|
||||
b.add_soft_link("soft", "/x/y");
|
||||
b.add_soft_link("dangling", "/nowhere");
|
||||
b.add_hard_link("alias", "/x/y");
|
||||
b.add_external_link("ext", "other.h5", "/data");
|
||||
let mut g = b.create_group("a/b");
|
||||
g.set_attr("merged", AttrValue::I64(1));
|
||||
for i in 0..10 {
|
||||
g.set_attr(&format!("attr{i}"), AttrValue::F64(i as f64));
|
||||
}
|
||||
b.add_group(g.finish());
|
||||
let mut g = b.create_group("ordered");
|
||||
g.track_order(true);
|
||||
for i in (0..40).rev() {
|
||||
g.create_dataset(&format!("n{i:02}")).with_i32_data(&[i]);
|
||||
}
|
||||
g.add_hard_link("back", "/a/b/c");
|
||||
b.add_group(g.finish());
|
||||
let mut g = b.create_group("compact_ordered");
|
||||
g.track_order(true);
|
||||
g.create_dataset("z").with_i32_data(&[1]);
|
||||
g.create_dataset("a").with_i32_data(&[2]);
|
||||
b.add_group(g.finish());
|
||||
let nested = dir.join("nested.h5");
|
||||
b.write(&nested).unwrap();
|
||||
|
||||
let mut b = FileBuilder::new();
|
||||
let mut g = b.create_group("many");
|
||||
for i in 0..10_000 {
|
||||
g.create_dataset(&format!("d{i:05}")).with_i32_data(&[i]);
|
||||
}
|
||||
b.add_group(g.finish());
|
||||
let many = dir.join("many.h5");
|
||||
b.write(&many).unwrap();
|
||||
[nested, many]
|
||||
.iter()
|
||||
.map(|p| p.to_string_lossy().into_owned())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_and_dump_files_with_nested_groups_and_links() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let files = write_nested_links(dir.path());
|
||||
// `--data` reads every dataset by path, and a lookup in a dense group
|
||||
// scans all of its links: 10 000 datasets take minutes in a debug
|
||||
// build, so the big file is checked structurally only (and not dumped).
|
||||
for (p, data) in [(&files[0], true), (&files[1], false)] {
|
||||
let args: &[&str] = if data {
|
||||
&["check", "--data", p]
|
||||
} else {
|
||||
&["check", p]
|
||||
};
|
||||
let o = h5rs(args);
|
||||
assert_eq!(code(&o), 0, "{p}:\n{}", stdout(&o));
|
||||
assert!(stdout(&o).contains("no problems found"), "{}", stdout(&o));
|
||||
}
|
||||
if missing(tool_available("h5dump"), "h5dump") {
|
||||
return;
|
||||
}
|
||||
for p in &files[..1] {
|
||||
let name = Path::new(p).file_name().unwrap().to_string_lossy();
|
||||
let ours = h5rs(&["dump", p]);
|
||||
assert!(ours.status.success(), "{p}: {ours:?}");
|
||||
let reference = run("h5dump", &[p]);
|
||||
assert!(reference.status.success(), "h5dump {p}: {reference:?}");
|
||||
let r = stdout(&reference).replacen(p.as_str(), &name, 1);
|
||||
assert_eq!(stdout(&ours), r, "{name}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_files_with_big_dense_storage() {
|
||||
// Dense links and attributes past the 512 KiB the root indirect block's
|
||||
// direct blocks hold: the heap then needs child indirect blocks, which
|
||||
// the writer used to write as direct blocks ("fractal heap indirect
|
||||
// block: bad signature").
|
||||
use clawhdf5::{AttrValue, FileBuilder};
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let mut b = FileBuilder::new();
|
||||
let x = b.create_dataset("x");
|
||||
x.with_i32_data(&[7]);
|
||||
for i in 0..150usize {
|
||||
let len = if i % 3 == 0 { 7_000 } else { 1 + i };
|
||||
x.set_attr(
|
||||
&format!("a{i:03}"),
|
||||
AttrValue::F64Array(vec![i as f64; len]),
|
||||
);
|
||||
}
|
||||
let mut g = b.create_group("g");
|
||||
for i in 0..40_000 {
|
||||
g.add_hard_link(&format!("link_{i:06}_{}", "x".repeat(88)), "/x");
|
||||
}
|
||||
b.add_group(g.finish());
|
||||
let p = dir.path().join("big.h5").to_string_lossy().into_owned();
|
||||
b.write(&p).unwrap();
|
||||
// Structure only: `--data` looks every link up by a linear scan.
|
||||
let o = h5rs(&["check", &p]);
|
||||
assert_eq!(code(&o), 0, "{p}:\n{}", stdout(&o));
|
||||
assert!(stdout(&o).contains("no problems found"), "{}", stdout(&o));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user