mod test_utils;
use test_utils::*;
#[test]
fn test_prescaled_sdpa_coalesced() {
let graph = load_onnx_simplified("prescaled_sdpa.onnx");
let attention = graph
.nodes
.iter()
.find(|n| matches!(n, onnx_ir::ir::Node::Attention { .. }));
assert!(
attention.is_some(),
"Pre-scaled SDPA pattern should be coalesced into an Attention node"
);
if let Some(onnx_ir::ir::Node::Attention(node)) = attention {
assert!(
node.config.scale.is_none(),
"Dynamic pre-scale should result in default scale (None)"
);
}
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Softmax { .. })),
"Softmax should be absorbed into Attention node"
);
}
#[test]
fn test_prescaled_sdpa_not_coalesced_without_simplify() {
let graph = load_onnx("prescaled_sdpa.onnx");
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Attention { .. })),
"Attention node should not appear without simplification"
);
assert!(
has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Softmax { .. })),
"Softmax should remain without simplification"
);
}
#[test]
fn test_constant_fold_cascade() {
let graph = load_onnx_simplified("constant_fold_cascade.onnx");
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Mul { .. })),
"Mul should be folded into a constant"
);
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Gather { .. })),
"Gather should be folded into a constant"
);
assert_eq!(
count_operation_nodes(&graph),
0,
"only constants should remain"
);
}
#[test]
fn test_constant_fold_cascade_without_simplify() {
let graph = load_onnx("constant_fold_cascade.onnx");
assert!(
has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Mul { .. })),
"Mul should remain without simplification"
);
assert!(
has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Gather { .. })),
"Gather should remain without simplification"
);
}
#[test]
fn test_constant_fold_chain() {
let graph = load_onnx_simplified("constant_fold_chain.onnx");
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Add { .. })),
"Add should be folded"
);
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Sub { .. })),
"Sub should be folded"
);
assert_eq!(
count_operation_nodes(&graph),
0,
"only constants should remain"
);
}
#[test]
fn test_constant_fold_blocked_by_dynamic() {
let graph = load_onnx_simplified("constant_fold_blocked.onnx");
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Neg { .. })),
"Neg on constant should be folded"
);
assert!(
has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Add { .. })),
"Add with dynamic input should NOT be folded"
);
}
#[test]
fn test_constant_fold_concat() {
let graph = load_onnx_simplified("constant_fold_concat.onnx");
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Concat { .. })),
"Concat of constants should be folded"
);
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Slice { .. })),
"Slice on Shape should be folded by constant_shape"
);
assert_eq!(
count_operation_nodes(&graph),
0,
"only constants should remain"
);
}
#[test]
fn test_constant_fold_cast() {
let graph = load_onnx_simplified("constant_fold_cast.onnx");
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Cast { .. })),
"Cast on constant should be folded"
);
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Gather { .. })),
"Gather should be folded by constant_shape"
);
assert_eq!(
count_operation_nodes(&graph),
0,
"only constants should remain"
);
}
#[test]
fn test_constant_fold_sqrt() {
let graph = load_onnx_simplified("constant_fold_sqrt.onnx");
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Sqrt { .. })),
"Sqrt on constant should be folded"
);
assert!(
!has_node_type(&graph, |n| matches!(n, onnx_ir::ir::Node::Cast { .. })),
"Cast on constant should be folded"
);
assert_eq!(
count_operation_nodes(&graph),
0,
"only constants should remain"
);
}