//! Unit tests for the TIR graph.

#[cfg(test)]
mod tests {
    use crate::ir::tir::TIROp;
    use crate::neural::data::tir_graph::*;

    #[test]
    fn simple_arithmetic_graph() {
        // push 3; push 4; add -> 3 nodes
        let ops = vec![TIROp::Push(3), TIROp::Push(4), TIROp::Add];
        let graph = TirGraph::from_tir_ops(&ops);

        assert_eq!(graph.num_nodes(), 3);
        // ControlFlow: push3->push4, push4->add = 2
        assert_eq!(graph.count_edges(EdgeKind::ControlFlow), 2);
        // DataDep: push3->add, push4->add = 2
        assert_eq!(graph.count_edges(EdgeKind::DataDep), 2);
        assert_eq!(graph.count_edges(EdgeKind::MemOrder), 0);
    }

    #[test]
    fn memory_ops_get_mem_order_edges() {
        let ops = vec![
            TIROp::Push(100),
            TIROp::ReadMem(1),
            TIROp::Push(200),
            TIROp::WriteMem(1),
        ];
        let graph = TirGraph::from_tir_ops(&ops);

        assert_eq!(graph.num_nodes(), 4);
        assert!(graph.count_edges(EdgeKind::MemOrder) >= 1);
    }

    #[test]
    fn if_else_creates_branch_edges() {
        let ops = vec![
            TIROp::Push(1), // condition
            TIROp::IfElse {
                then_body: vec![TIROp::Push(10)],
                else_body: vec![TIROp::Push(20)],
            },
        ];
        let graph = TirGraph::from_tir_ops(&ops);

        // 4 nodes: Push(1), IfElse, Push(10), Push(20)
        assert_eq!(graph.num_nodes(), 4);
        // ControlFlow edges include branch edges to both bodies
        let cf = graph.count_edges(EdgeKind::ControlFlow);
        assert!(cf >= 3, "expected >=3 CF edges, got {}", cf);
    }

    #[test]
    fn loop_creates_back_edge() {
        let ops = vec![
            TIROp::Push(5),
            TIROp::Loop {
                label: "l".into(),
                body: vec![TIROp::Push(1), TIROp::Sub],
            },
        ];
        let graph = TirGraph::from_tir_ops(&ops);

        // 4 nodes: Push(5), Loop, Push(1), Sub
        assert_eq!(graph.num_nodes(), 4);
        // Should have a back edge from Sub -> Loop
        let has_back_edge = graph
            .edges
            .iter()
            .any(|(from, to, kind)| *kind == EdgeKind::ControlFlow && *from == 3 && *to == 1);
        assert!(has_back_edge, "missing loop back edge");
    }

    #[test]
    fn feature_vector_dimensions() {
        let node = TirNode {
            op: OpKind::Add,
            field_type: FieldType::BFE,
            immediate: None,
        };
        let fv = node.feature_vector();
        assert_eq!(fv.len(), NODE_FEATURE_DIM);
        assert_eq!(fv.len(), 59);
        // Add is index 15
        assert_eq!(fv[15], 1.0);
        // BFE is index 54
        assert_eq!(fv[54], 1.0);
        // No immediate
        assert_eq!(fv[57], 0.0);
    }

    #[test]
    fn feature_vector_with_immediate() {
        let node = TirNode {
            op: OpKind::Push,
            field_type: FieldType::BFE,
            immediate: Some(42),
        };
        let fv = node.feature_vector();
        assert_eq!(fv[11], 1.0); // Push is index 11
        assert_eq!(fv[57], 1.0); // has_immediate = 1
        assert!(fv[58] > 0.0); // normalized immediate > 0
    }

    #[test]
    fn empty_ops_produces_empty_graph() {
        let graph = TirGraph::from_tir_ops(&[]);
        assert_eq!(graph.num_nodes(), 0);
        assert_eq!(graph.num_edges(), 0);
    }

    #[test]
    fn all_54_op_kinds_are_numbered() {
        assert_eq!(OpKind::Call as u8, 0);
        assert_eq!(OpKind::ProofBlock as u8, 53);
        assert_eq!(NUM_OP_KINDS, 54);
    }

    #[test]
    fn dup_creates_data_dep_without_consuming() {
        // push 7; dup 0 -> dup reads from push without consuming
        let ops = vec![TIROp::Push(7), TIROp::Dup(0)];
        let graph = TirGraph::from_tir_ops(&ops);

        assert_eq!(graph.num_nodes(), 2);
        // DataDep: push->dup (read dependency)
        assert_eq!(graph.count_edges(EdgeKind::DataDep), 1);
    }
}

Dimensions

trident/src/deploy/tests.rs
cw-cyber/contracts/hub-skills/src/tests.rs
trident/src/lsp/semantic/tests.rs
trident/src/syntax/format/tests.rs
cw-cyber/contracts/hub-libs/src/tests.rs
cw-cyber/contracts/hub-channels/src/tests.rs
trident/src/package/registry/tests.rs
trident/src/syntax/lexer/tests.rs
trident/src/cost/stack_verifier/tests.rs
cw-cyber/contracts/hub-networks/src/tests.rs
trident/src/verify/sym/tests.rs
cw-cyber/contracts/cw-cyber-subgraph/src/tests.rs
cw-cyber/contracts/cw-cyber-gift/src/tests.rs
trident/src/verify/report/tests.rs
trident/src/package/store/tests.rs
cw-cyber/contracts/hub-tokens/src/tests.rs
trident/src/config/scaffold/tests.rs
trident/src/verify/solve/tests.rs
trident/src/verify/smt/tests.rs
cw-cyber/contracts/graph-filter/src/tests.rs
trident/src/package/manifest/tests.rs
trident/src/verify/synthesize/tests.rs
cw-cyber/contracts/cw-cyber-passport/src/tests.rs
trident/src/verify/equiv/tests.rs
trident/src/lsp/util/tests.rs
trident/src/config/resolve/tests.rs
trident/src/package/hash/tests.rs
trident/src/ir/lir/tests.rs
cw-cyber/contracts/hub-protocols/src/tests.rs
trident/src/syntax/grammar/tests.rs
trident/src/ir/tir/optimize/tests.rs
trident/src/ir/tir/lower/tests.rs
trident/src/ir/tir/stack/tests.rs

Local Graph