Files
photocraft/crates/psd/tests/it/common/atn_roundtrip.rs
T
David Mann 4b053e15ae Integration: keep the ATN contract tests, drop the extra workflow (#7561)
The contract tests no longer compiled on main (AtnItem::dictionary is now
Vec<u8>, so it is compared with b"Future event"), sat outside main's
tests/it layout, and the new atn.yml added six legs (two macOS) to every
PR against ci.yml's policy. Move the tests into tests/it so the existing
CI runs them, drop atn.yml and docs/atn-testing.md, keep main's ci.yml and
fuzz target, and note the committed fixtures in ATTRIBUTION.md.

Co-authored-by: denstu473 <63150090+denstu473@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 14:25:51 +01:00

72 lines
2.3 KiB
Rust

//! Shared round-trip invariant for the `.atn` parser contract suite.
use photocraft_psd::atn::{self, AtnFile};
use photocraft_psd::descriptor::{Descriptor, Value};
fn scalar(value: &mut f64, bits: &mut Vec<u64>) {
bits.push(value.to_bits());
// AST equality must remain meaningful when a valid descriptor contains NaN.
if value.is_nan() {
*value = 0.0;
}
}
fn descriptor(desc: &mut Descriptor, bits: &mut Vec<u64>) {
for (_, item) in &mut desc.items {
value(item, bits);
}
}
fn value(item: &mut Value, bits: &mut Vec<u64>) {
match item {
Value::Double(v) | Value::UnitFloat { value: v, .. } => scalar(v, bits),
Value::UnitFloats { values, .. } => {
for v in values {
scalar(v, bits);
}
}
Value::Descriptor(d) | Value::GlobalObject(d) => descriptor(d, bits),
Value::ObjectArray(array) => descriptor(&mut array.body, bits),
Value::List(items) => {
for item in items {
value(item, bits);
}
}
Value::Reference(_)
| Value::Text(_)
| Value::Enumerated { .. }
| Value::Integer(_)
| Value::LargeInteger(_)
| Value::Boolean(_)
| Value::Class(_)
| Value::GlobalClass(_)
| Value::Alias(_)
| Value::Path(_)
| Value::RawData(_) => {}
}
}
fn floats(file: &mut AtnFile) -> Vec<u64> {
let mut bits = Vec::new();
for action in &mut file.actions {
for item in &mut action.items {
if let Some(d) = &mut item.descriptor {
descriptor(d, &mut bits);
}
}
}
bits
}
pub fn check(data: &[u8]) {
if let Ok(mut original) = atn::parse(data) {
let encoded = atn::write(&original).expect("a parsed set is writable");
let mut again = atn::parse(&encoded).expect("a written set parses");
assert_eq!(atn::write(&again).expect("a reparsed set is writable"), encoded);
assert_eq!(floats(&mut original), floats(&mut again), "every floating-point bit pattern survives");
// Trailing-input diagnostics are not serialized into an action set.
original.warnings.clear();
again.warnings.clear();
assert_eq!(again, original, "set metadata, action metadata and every descriptor value survive");
}
}