use super::*;
use ifc_lite_core::EntityDecoder;
#[test]
fn parse_first_ref_reads_an_ordinary_ref() {
assert_eq!(parse_first_ref(b"#5=IFCFACETEDBREP(#137924)"), Some(137924));
}
#[test]
fn parse_first_ref_accepts_a_ref_at_exactly_u32_max() {
assert_eq!(
parse_first_ref(b"#5=IFCFACETEDBREP(#4294967295)"),
Some(u32::MAX)
);
}
#[test]
fn parse_first_ref_refuses_a_ref_above_u32_max_instead_of_wrapping_onto_a_real_entity() {
assert_eq!(parse_first_ref(b"#5=IFCFACETEDBREP(#4294967297)"), None);
}
#[test]
fn item_signature_refuses_an_oversized_child_ref_instead_of_aliasing_it_onto_a_real_entity() {
let content = b"#1=IFCCARTESIANPOINT((0.,0.,0.));\n\
#2=IFCEXTRUDEDAREASOLID(#4294967297);\n\
#3=IFCEXTRUDEDAREASOLID(#999999999);\n\
#4=IFCEXTRUDEDAREASOLID(#1);\n";
let mut decoder = EntityDecoder::new(content);
let mut memo = FxHashMap::default();
let mut refused = 0usize;
let oversized_ref_sig = item_signature(&mut decoder, 2, &mut memo, &mut refused);
let mut decoder = EntityDecoder::new(content);
let mut memo = FxHashMap::default();
let mut refused2 = 0usize;
let missing_ref_sig = item_signature(&mut decoder, 3, &mut memo, &mut refused2);
let mut decoder = EntityDecoder::new(content);
let mut memo = FxHashMap::default();
let mut refused3 = 0usize;
let real_ref_sig = item_signature(&mut decoder, 4, &mut memo, &mut refused3);
assert_eq!(
oversized_ref_sig, missing_ref_sig,
"an oversized child ref must hash exactly like a genuinely missing ref"
);
assert_ne!(
oversized_ref_sig, real_ref_sig,
"an oversized child ref must NEVER hash like the real entity #1 it would wrap onto"
);
}
#[test]
fn item_signature_counts_an_oversized_child_ref_as_refused() {
let content = b"#1=IFCCARTESIANPOINT((0.,0.,0.));\n\
#2=IFCEXTRUDEDAREASOLID(#4294967297);\n";
let mut decoder = EntityDecoder::new(content);
let mut memo = FxHashMap::default();
let mut refused = 0usize;
item_signature(&mut decoder, 2, &mut memo, &mut refused);
assert_eq!(
refused, 1,
"an oversized child ref must be counted, not silently dropped (#3752)"
);
}
#[test]
fn item_signature_reports_no_refusals_for_an_ordinary_ref() {
let content = b"#1=IFCCARTESIANPOINT((0.,0.,0.));\n\
#2=IFCEXTRUDEDAREASOLID(#1);\n";
let mut decoder = EntityDecoder::new(content);
let mut memo = FxHashMap::default();
let mut refused = 0usize;
item_signature(&mut decoder, 2, &mut memo, &mut refused);
assert_eq!(refused, 0, "an ordinary reference must not be counted as refused");
}
#[test]
fn item_signature_reports_no_refusals_for_a_ref_at_exactly_u32_max() {
let content = b"#4294967295=IFCCARTESIANPOINT((0.,0.,0.));\n\
#2=IFCEXTRUDEDAREASOLID(#4294967295);\n";
let mut decoder = EntityDecoder::new(content);
let mut memo = FxHashMap::default();
let mut refused = 0usize;
item_signature(&mut decoder, 2, &mut memo, &mut refused);
assert_eq!(refused, 0, "a ref at exactly u32::MAX must not be counted as refused");
}
#[test]
fn geometry_routing_key_feeds_take_content_hash_oversized_ref_drops() {
use ifc_lite_core::{AttributeValue, DecodedEntity, IfcType};
let content = b"#2=IFCEXTRUDEDAREASOLID(#4294967297);\n";
let mut decoder = EntityDecoder::new(content);
let element = DecodedEntity::new(
1,
IfcType::IfcWall,
vec![
AttributeValue::Null,
AttributeValue::Null,
AttributeValue::Null,
AttributeValue::Null,
AttributeValue::Null,
AttributeValue::Null,
AttributeValue::EntityRef(2), ],
);
let router = crate::GeometryRouter::new();
let key = router.geometry_routing_key(&element, &mut decoder);
assert!(key.is_some(), "an element with a representation must still get a routing key");
assert_eq!(
router.take_content_hash_oversized_ref_drops(),
1,
"the oversized child ref hit while routing must be counted (#3752)"
);
assert_eq!(
router.take_content_hash_oversized_ref_drops(),
0,
"a second drain must return zero — the counter resets, it isn't recomputed"
);
}