# defmodule Tilly.BDDTest do # use ExUnit.Case, async: true # # alias Tilly.BDD.Node # # describe "init_bdd_store/1" do # test "initializes bdd_store in typing_ctx with predefined false and true nodes" do # typing_ctx = %{} # new_ctx = Tilly.BDD.init_bdd_store(typing_ctx) # # assert %{bdd_store: bdd_store} = new_ctx # assert is_map(bdd_store.nodes_by_structure) # assert is_map(bdd_store.structures_by_id) # assert bdd_store.next_node_id == 2 # 0 for false, 1 for true # assert bdd_store.ops_cache == %{} # # # Check false node # false_id = Tilly.BDD.false_node_id() # false_ops_module = Tilly.BDD.universal_ops_module() # assert bdd_store.nodes_by_structure[{Node.mk_false(), false_ops_module}] == false_id # assert bdd_store.structures_by_id[false_id] == %{structure: Node.mk_false(), ops_module: false_ops_module} # # # Check true node # true_id = Tilly.BDD.true_node_id() # true_ops_module = Tilly.BDD.universal_ops_module() # assert bdd_store.nodes_by_structure[{Node.mk_true(), true_ops_module}] == true_id # assert bdd_store.structures_by_id[true_id] == %{structure: Node.mk_true(), ops_module: true_ops_module} # end # end # # describe "get_or_intern_node/3" do # setup do # typing_ctx = Tilly.BDD.init_bdd_store(%{}) # %{initial_ctx: typing_ctx} # end # # test "interning Node.mk_false() returns predefined false_id and doesn't change store", %{initial_ctx: ctx} do # false_ops_module = Tilly.BDD.universal_ops_module() # {new_ctx, node_id} = Tilly.BDD.get_or_intern_node(ctx, Node.mk_false(), false_ops_module) # assert node_id == Tilly.BDD.false_node_id() # assert new_ctx.bdd_store == ctx.bdd_store # end # # test "interning Node.mk_true() returns predefined true_id and doesn't change store", %{initial_ctx: ctx} do # true_ops_module = Tilly.BDD.universal_ops_module() # {new_ctx, node_id} = Tilly.BDD.get_or_intern_node(ctx, Node.mk_true(), true_ops_module) # assert node_id == Tilly.BDD.true_node_id() # assert new_ctx.bdd_store == ctx.bdd_store # end # # test "interning a new leaf node returns a new ID and updates the store", %{initial_ctx: ctx} do # leaf_structure = Node.mk_leaf("test_leaf") # ops_mod = :my_ops # # {ctx_after_intern, node_id} = Tilly.BDD.get_or_intern_node(ctx, leaf_structure, ops_mod) # # assert node_id == 2 # Initial next_node_id # assert ctx_after_intern.bdd_store.next_node_id == 3 # assert ctx_after_intern.bdd_store.nodes_by_structure[{leaf_structure, ops_mod}] == node_id # assert ctx_after_intern.bdd_store.structures_by_id[node_id] == %{structure: leaf_structure, ops_module: ops_mod} # end # # test "interning the same leaf node again returns the same ID and doesn't change store", %{initial_ctx: ctx} do # leaf_structure = Node.mk_leaf("test_leaf") # ops_mod = :my_ops # # {ctx_after_first_intern, first_node_id} = Tilly.BDD.get_or_intern_node(ctx, leaf_structure, ops_mod) # {ctx_after_second_intern, second_node_id} = Tilly.BDD.get_or_intern_node(ctx_after_first_intern, leaf_structure, ops_mod) # # assert first_node_id == second_node_id # assert ctx_after_first_intern.bdd_store == ctx_after_second_intern.bdd_store # end # # test "interning a new split node returns a new ID and updates the store", %{initial_ctx: ctx} do # split_structure = Node.mk_split(:el, Tilly.BDD.true_node_id(), Tilly.BDD.false_node_id(), Tilly.BDD.true_node_id()) # ops_mod = :split_ops # # {ctx_after_intern, node_id} = Tilly.BDD.get_or_intern_node(ctx, split_structure, ops_mod) # # assert node_id == 2 # Initial next_node_id # assert ctx_after_intern.bdd_store.next_node_id == 3 # assert ctx_after_intern.bdd_store.nodes_by_structure[{split_structure, ops_mod}] == node_id # assert ctx_after_intern.bdd_store.structures_by_id[node_id] == %{structure: split_structure, ops_module: ops_mod} # end # # test "interning structurally identical nodes with different ops_modules results in different IDs", %{initial_ctx: ctx} do # leaf_structure = Node.mk_leaf("shared_leaf") # ops_mod1 = :ops1 # ops_mod2 = :ops2 # # {ctx1, id1} = Tilly.BDD.get_or_intern_node(ctx, leaf_structure, ops_mod1) # {_ctx2, id2} = Tilly.BDD.get_or_intern_node(ctx1, leaf_structure, ops_mod2) # # assert id1 != id2 # assert id1 == 2 # assert id2 == 3 # end # # test "raises ArgumentError if bdd_store is not initialized" do # assert_raise ArgumentError, ~r/BDD store not initialized/, fn -> # Tilly.BDD.get_or_intern_node(%{}, Node.mk_leaf("foo"), :ops) # end # end # end # # describe "get_node_data/2" do # setup do # ctx = Tilly.BDD.init_bdd_store(%{}) # leaf_structure = Node.mk_leaf("data") # ops_mod = :leaf_ops # {new_ctx, leaf_id_val} = Tilly.BDD.get_or_intern_node(ctx, leaf_structure, ops_mod) # %{ctx: new_ctx, leaf_structure: leaf_structure, ops_mod: ops_mod, leaf_id: leaf_id_val} # end # # test "returns correct data for false node", %{ctx: ctx} do # false_id = Tilly.BDD.false_node_id() # false_ops_module = Tilly.BDD.universal_ops_module() # assert Tilly.BDD.get_node_data(ctx, false_id) == %{structure: Node.mk_false(), ops_module: false_ops_module} # end # # test "returns correct data for true node", %{ctx: ctx} do # true_id = Tilly.BDD.true_node_id() # true_ops_module = Tilly.BDD.universal_ops_module() # assert Tilly.BDD.get_node_data(ctx, true_id) == %{structure: Node.mk_true(), ops_module: true_ops_module} # end # # test "returns correct data for a custom interned leaf node", %{ctx: ctx, leaf_structure: ls, ops_mod: om, leaf_id: id} do # assert Tilly.BDD.get_node_data(ctx, id) == %{structure: ls, ops_module: om} # end # # test "returns nil for an unknown node ID", %{ctx: ctx} do # assert Tilly.BDD.get_node_data(ctx, 999) == nil # end # # test "returns nil if bdd_store not in ctx" do # assert Tilly.BDD.get_node_data(%{}, 0) == nil # end # end # # describe "is_false_node?/2 and is_true_node?/2" do # setup do # ctx = Tilly.BDD.init_bdd_store(%{}) # leaf_structure = Node.mk_leaf("data") # ops_mod = :leaf_ops # {new_ctx, leaf_id_val} = Tilly.BDD.get_or_intern_node(ctx, leaf_structure, ops_mod) # %{ctx: new_ctx, leaf_id: leaf_id_val} # end # # test "is_false_node?/2", %{ctx: ctx, leaf_id: id} do # assert Tilly.BDD.is_false_node?(ctx, Tilly.BDD.false_node_id()) == true # assert Tilly.BDD.is_false_node?(ctx, Tilly.BDD.true_node_id()) == false # assert Tilly.BDD.is_false_node?(ctx, id) == false # assert Tilly.BDD.is_false_node?(ctx, 999) == false # Unknown ID # end # # test "is_true_node?/2", %{ctx: ctx, leaf_id: id} do # assert Tilly.BDD.is_true_node?(ctx, Tilly.BDD.true_node_id()) == true # assert Tilly.BDD.is_true_node?(ctx, Tilly.BDD.false_node_id()) == false # assert Tilly.BDD.is_true_node?(ctx, id) == false # assert Tilly.BDD.is_true_node?(ctx, 999) == false # Unknown ID # end # end # end