trellis-core 0.1.2

Deterministic reactive resource graph core types.
Documentation
use std::collections::BTreeMap;

use trellis_core::{DependencyList, Graph};

#[test]
fn debug_dump_is_deterministic() {
    fn build_graph() -> Graph {
        let mut graph = Graph::new();
        let mut tx = graph.begin_transaction().unwrap();
        let root = tx.create_scope("root").unwrap();
        let workspace = tx
            .create_scope_with_parent("workspace", Some(root))
            .unwrap();
        let active = tx.input::<String>("active_workspace").unwrap();
        let visible = tx
            .derived::<Vec<String>>(
                "visible_projects",
                DependencyList::new([active.id()]).unwrap(),
                |_| Ok(Vec::new()),
            )
            .unwrap();
        let windows = tx
            .collection::<String, String>(
                "sync_windows",
                DependencyList::new([active.id(), visible.id()]).unwrap(),
                |_| Ok(BTreeMap::new()),
            )
            .unwrap();

        tx.attach_node_to_scope(visible, workspace).unwrap();
        tx.attach_node_to_scope(windows, workspace).unwrap();
        tx.commit().unwrap();
        drop(tx);
        graph
    }

    let first = build_graph().debug_dump();
    let second = build_graph().debug_dump();

    assert_eq!(first, second);
    assert_eq!(
        first,
        concat!(
            "Graph(revision=1)\n",
            "Scopes:\n",
            "  ScopeId(1) name=\"root\" parent=None closed=false\n",
            "  ScopeId(2) name=\"workspace\" parent=Some(ScopeId(1)) closed=false\n",
            "Nodes:\n",
            "  NodeId(1) kind=Input name=\"active_workspace\" scope=None deps=[]\n",
            "  NodeId(2) kind=Derived name=\"visible_projects\" scope=Some(ScopeId(2)) deps=[NodeId(1)]\n",
            "  NodeId(3) kind=Collection name=\"sync_windows\" scope=Some(ScopeId(2)) deps=[NodeId(1), NodeId(2)]\n",
            "Dependency paths:\n",
            "  NodeId(1) -> NodeId(2)\n",
            "  NodeId(1) -> NodeId(3)\n",
            "  NodeId(2) -> NodeId(3)\n",
            "Resources:\n",
            "Outputs:\n",
            "Audit:\n",
            "  tx=TransactionId(1) revision=Revision(1) event=ScopeCreated(ScopeId(1))\n",
            "  tx=TransactionId(1) revision=Revision(1) event=ScopeCreated(ScopeId(2))\n",
            "  tx=TransactionId(1) revision=Revision(1) event=NodeCreated(NodeId(1))\n",
            "  tx=TransactionId(1) revision=Revision(1) event=NodeCreated(NodeId(2))\n",
            "  tx=TransactionId(1) revision=Revision(1) event=NodeCreated(NodeId(3))\n",
            "  tx=TransactionId(1) revision=Revision(1) event=NodeAttached { node: NodeId(2), scope: ScopeId(2) }\n",
            "  tx=TransactionId(1) revision=Revision(1) event=NodeAttached { node: NodeId(3), scope: ScopeId(2) }\n",
            "  tx=TransactionId(1) revision=Revision(1) event=DerivedChanged(NodeId(2))\n",
        )
    );
}