use super::{read, read_projection, write_data};
use crate::core::{CellKind, Dataset, Field, FieldLocation};
use crate::formats::bdf;
#[test]
fn all_linear_cells_ids_and_fields_roundtrip() {
let mesh = bdf::mesh::read(include_bytes!(
"../../../../tests/fixtures/mixed-linear.bdf"
))
.unwrap()
.mesh;
let dataset = Dataset {
fields: vec![
Field {
name: "velocity".into(),
location: FieldLocation::Point,
components: vec!["C1".into(), "C2".into(), "C3".into()],
values: vec![0.5; mesh.points.len() * 3],
step: None,
time: None,
},
Field {
name: "energy".into(),
location: FieldLocation::Cell,
components: vec!["C1".into()],
values: (0..mesh.cells.len())
.map(|index| f64::from(u32::try_from(index).unwrap()))
.collect(),
step: None,
time: None,
},
],
mesh,
};
let mut bytes = Vec::new();
write_data(&dataset, &mut bytes).unwrap();
let read = read(std::str::from_utf8(&bytes).unwrap()).unwrap();
assert_eq!(read, dataset);
}
#[test]
fn missing_ids_are_reported_and_assigned() {
let source = "# vtk DataFile Version 2.0\nexample\nASCII\nDATASET UNSTRUCTURED_GRID\nPOINTS 2 float\n0 0 0 1 0 0\nCELLS 1 3\n2 0 1\nCELL_TYPES 1\n3\nPOINT_DATA 2\nSCALARS temperature double 1\nLOOKUP_TABLE default\n1.5 2.5\n";
let projection = read_projection(source).unwrap();
assert!(projection.generated_point_ids);
assert!(projection.generated_cell_ids);
assert_eq!(projection.dataset.mesh.points[0].id, 1);
assert_eq!(projection.dataset.fields[0].values, [1.5, 2.5]);
}
#[test]
fn vtk_written_offsets_fixture_preserves_ids_and_topology() {
let dataset = read(include_str!("../../../../tests/fixtures/vtk-5.1-mixed.vtk")).unwrap();
assert_eq!(dataset.mesh.points.len(), 9);
assert_eq!(dataset.mesh.cells.len(), 7);
assert_eq!(dataset.mesh.cells[0].id, 101);
assert_eq!(dataset.mesh.cells[6].kind, CellKind::Pyramid5);
assert_eq!(dataset.mesh.cells[6].connectivity, [0, 1, 2, 3, 8]);
}
#[test]
fn malformed_and_unsupported_inputs_fail() {
let source = "# vtk DataFile Version 2.0\nexample\nASCII\nDATASET UNSTRUCTURED_GRID\nPOINTS 2 float\n0 0 0 1 0 0\nCELLS 1 3\n2 0 2\nCELL_TYPES 1\n3\n";
assert!(read(source).is_err());
assert!(read(&source.replace("ASCII", "BINARY")).is_err());
assert!(read(&source.replace("CELL_TYPES 1\n3", "CELL_TYPES 1\n22")).is_err());
assert!(read(&source.replace("POINTS 2", "POINTS 999999999")).is_err());
}
#[test]
fn scalar_vector_and_integer_attributes_are_preserved() {
let source = "# vtk DataFile Version 2.0\nattributes\nASCII\nDATASET UNSTRUCTURED_GRID\nPOINTS 2 double\n0 0 0 1 0 0\nCELLS 1 3\n2 0 1\nCELL_TYPES 1\n3\nPOINT_DATA 2\nSCALARS temperature int\nLOOKUP_TABLE default\n2 3\nVECTORS velocity float\n1 2 3 4 5 6\nCELL_DATA 1\nSCALARS pressure unsigned_short 1\nLOOKUP_TABLE default\n7\n";
let dataset = read(source).unwrap();
assert_eq!(dataset.fields.len(), 3);
assert_eq!(dataset.fields[0].values, [2.0, 3.0]);
assert_eq!(dataset.fields[1].values, [1., 2., 3., 4., 5., 6.]);
assert_eq!(dataset.fields[2].location, FieldLocation::Cell);
assert_eq!(dataset.fields[2].values, [7.]);
}
#[test]
fn malformed_legacy_attributes_and_offsets_are_rejected() {
let base = "# vtk DataFile Version 2.0\nmalformed\nASCII\nDATASET UNSTRUCTURED_GRID\nPOINTS 2 float\n0 0 0 1 0 0\nCELLS 1 3\n2 0 1\nCELL_TYPES 1\n3\n";
for suffix in [
"POINT_DATA 2\nSCALARS bad int 1\nLOOKUP_TABLE default\n9007199254740993 1\n",
"POINT_DATA 2\nSCALARS bad bit 1\nLOOKUP_TABLE default\n0 1\n",
"POINT_DATA 2\nSCALARS bad double 0\nLOOKUP_TABLE default\n0 1\n",
"POINT_DATA 2\nSCALARS bad double 1\nLOOKUP_TABLE rainbow\n0 1\n",
"POINT_DATA 2\nFIELD FieldData 1\nnastran_node_id 1 2 double\n1 2\n",
"POINT_DATA 2\nSCALARS same double 1\nLOOKUP_TABLE default\n0 1\nSCALARS same double 1\nLOOKUP_TABLE default\n0 1\n",
"POINT_DATA 2\nFIELD FieldData 1\nnastran_node_id 1 2 int\n0 2\n",
"CELL_DATA 2\nSCALARS bad double 1\nLOOKUP_TABLE default\n0 1\n",
"POINT_DATA 2\nFIELD FieldData 1\nshort 2 3 float\n0 1 2 3 4 5\n",
"POINT_DATA 2\nTEXTURE_COORDINATES uv 2 float\n0 0 1 0\n",
] {
let error = read(&format!("{base}{suffix}")).unwrap_err();
assert_eq!(error.code, "E_VTK", "{suffix}");
}
let offset_base = base.replace(
"CELLS 1 3\n2 0 1",
"CELLS 2 2\nOFFSETS vtktypeint64\n0 1\nCONNECTIVITY vtktypeint64\n0 1",
);
assert_eq!(read(&offset_base).unwrap_err().code, "E_VTK");
let unsupported_type = base.replace(
"CELLS 1 3\n2 0 1",
"CELLS 2 2\nOFFSETS float\n0 2\nCONNECTIVITY vtktypeint64\n0 1",
);
assert_eq!(read(&unsupported_type).unwrap_err().code, "E_VTK");
}
#[test]
fn malformed_legacy_grid_metadata_has_specific_diagnostics() {
let base = "# vtk DataFile Version 2.0\ngeometry\nASCII\nDATASET UNSTRUCTURED_GRID\nPOINTS 2 float\n0 0 0 1 0 0\nCELLS 1 3\n2 0 1\nCELL_TYPES 1\n3\n";
for (old, new, expected) in [
(
"POINTS 2 float",
"POINTS 2 int",
"POINTS require float or double",
),
("0 0 0 1 0 0", "0 0 0 NaN 0 0", "nonfinite VTK value"),
("CELLS 1 3", "CELLS 1 2", "cell list exceeds declared size"),
("CELLS 1 3", "CELLS 1 4", "cell list size mismatch"),
("2 0 1", "9 0 1", "unsupported higher-order cell width"),
("CELL_TYPES 1", "CELL_TYPES 2", "cell type count mismatch"),
(
"CELL_TYPES 1\n3",
"CELL_TYPES 1\n5",
"cell arity does not match",
),
] {
let changed = base.replacen(old, new, 1);
let error = read_projection(&changed).unwrap_err();
assert!(error.message.contains(expected), "{new}: {error}");
}
for source in [
base.replace("# vtk", "# wrong"),
base.replace("ASCII", "ASC\0II"),
format!("{base}UNKNOWN 1\n"),
format!("{base}POINT_DATA 2\nPOINT_DATA 2\n"),
] {
assert_eq!(read_projection(&source).unwrap_err().code, "E_VTK");
}
}