| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- function routes_to(model, source_id::Int, source_port::Symbol, target_id::Int, target_port::Symbol)
- source_key = (source_id, source_port)
- if !haskey(model.couplings, source_key)
- return false
- end
- targets = model.couplings[source_key]
- return any(t -> t[1] == target_id && t[2] == target_port, targets)
- end
- @testset "Self Loops" begin
- top = CoupledDEVS(:TopModel)
- add_in_port!(top, :in)
- add_out_port!(top, :out)
- forwarder_ref = add_submodel!(top, :forwarder, MockNode;
- inbox=(; in=Int[]),
- out_ports=(; out=Int),
- forward=true
- )
- connect!(top, self.out, self.in)
- @test_throws IllegalCouplingError compile_devs(top)
- empty!(top.couplings)
- connect!(top, forwarder_ref.out, forwarder_ref.in)
- @test_throws IllegalCouplingError compile_devs(top)
- end
- @testset "Static Cyclic Couplings" begin
- top = CoupledDEVS(:Top)
- nodeA_ref = add_submodel!(top, :NodeA, MockNode;
- inbox=(; in=Int[]),
- out_ports=(; out=Int),
- make_out=true, ta=1.0
- )
- nodeB_ref = add_submodel!(top, :NodeB, MockNode;
- inbox=(; in=Int[]),
- out_ports=(; out=Int),
- make_out=true,
- )
- connect!(top, nodeA_ref.out, nodeB_ref.in)
- connect!(top, nodeB_ref.out, nodeA_ref.in)
- model = compile_devs(top)
- id_A = model.path_to_id["Top.NodeA"]
- id_B = model.path_to_id["Top.NodeB"]
- # Check A -> B exists
- @test haskey(model.couplings, (id_A, :out))
- @test routes_to(model, id_A, :out, id_B, :in)
- # @test (id_B, :in) in model.couplings[(id_A, :out)]
- # Check B -> A exists
- @test haskey(model.couplings, (id_B, :out))
- @test routes_to(model, id_B, :out, id_A, :in)
- # @test (id_A, :in) in model.couplings[(id_B, :out)]
- end
- @testset "Atomic Input Couplings" begin
- top = CoupledDEVS(:top)
- add_in_port!(top, :in)
- add_out_port!(top, :out)
- inner = CoupledDEVS(:inner)
- add_in_port!(inner, :in)
- add_out_port!(inner, :out)
- atomic_ref1 = add_submodel!(top, :atomic1, MockNode;
- inbox=(; in=Int[]),
-
- )
- atomic_ref2 = add_submodel!(top, :atomic2, MockNode;
- inbox=(; in=Int[]),
- out_ports=(; out=Int),
- make_out=true
- )
- inner_ref = add_submodel!(top, :inner, inner)
- # atomic in -> atomic in
- connect!(top, atomic_ref1.in, atomic_ref2.in)
- @test_throws IllegalCouplingError compile_devs(top)
- empty!(top.couplings)
- # atomic in -> atomic out
- connect!(top, atomic_ref1.in, atomic_ref2.out)
- @test_throws IllegalCouplingError compile_devs(top)
- empty!(top.couplings)
- # atomic in -> coupled in
- connect!(top, atomic_ref1.in, inner_ref.in)
- @test_throws IllegalCouplingError compile_devs(top)
- empty!(top.couplings)
- # atomic in -> coupled out
- connect!(top, atomic_ref1.in, inner_ref.out)
- @test_throws IllegalCouplingError compile_devs(top)
- empty!(top.couplings)
- # atomic in -> parent coupled in
- connect!(top, atomic_ref1.in, self.in)
- @test_throws IllegalCouplingError compile_devs(top)
- empty!(top.couplings)
- # atomic in -> parent coupled out
- connect!(top, atomic_ref1.in, self.out)
- @test_throws IllegalCouplingError compile_devs(top)
- empty!(top.couplings)
- end
- @testset "Atomic Output Couplings" begin
- top = CoupledDEVS(:top)
- add_in_port!(top, :in)
- add_out_port!(top, :out)
- inner = CoupledDEVS(:InnerModel)
- add_in_port!(inner, :in)
- add_out_port!(inner, :out)
- atomic_ref1 = add_submodel!(top, :atomic1, MockNode;
- out_ports=(; out=Int),
- make_out=true
- )
- atomic_ref2 = add_submodel!(top, :atomic2, MockNode;
- inbox=(; in=Int[]),
- out_ports=(; out=Int),
- make_out=true
- )
- inner_ref = add_submodel!(top, :inner, inner)
- # HAPPY PATHS
- # atomic out -> atomic in
- connect!(top, atomic_ref1.out, atomic_ref2.in)
- model = compile_devs(top)
- atomic1_id = model.path_to_id["top.atomic1"]
- atomic2_id = model.path_to_id["top.atomic2"]
- @test haskey(model.couplings, (atomic1_id, :out))
- @test routes_to(model, atomic1_id, :out, atomic2_id, :in)
- empty!(top.couplings)
- # atomic out -> coupled in
- connect!(top, atomic_ref1.out, inner_ref.in)
- model = compile_devs(top)
- @test model !== nothing
- empty!(top.couplings)
- # atomic out -> parent coupled out
- connect!(top, atomic_ref1.out, self.out)
- model = compile_devs(top)
- @test model !== nothing
- empty!(top.couplings)
- # SAD
- # atomic out -> atomic out
- connect!(top, atomic_ref1.out, atomic_ref2.out)
- @test_throws IllegalCouplingError compile_devs(top)
- empty!(top.couplings)
- # atomic out -> coupled out
- connect!(top, atomic_ref1.out, inner_ref.out)
- @test_throws IllegalCouplingError compile_devs(top)
- empty!(top.couplings)
- # atomic out -> parent coupled in
- connect!(top, atomic_ref1.out, self.in)
- @test_throws IllegalCouplingError compile_devs(top)
- empty!(top.couplings)
- end
- @testset "Static Flatten Connection" begin
- parent = CoupledDEVS(:parent)
- child1 = CoupledDEVS(:child1)
- add_out_port!(child1, :out)
- child2 = CoupledDEVS(:child2)
- add_in_port!(child2, :in)
- sender_ref = add_submodel!(child1, :sender, MockNode;
- out_ports=(; out=Int),
- make_out=true, ta=1.0
- )
- receiver_ref = add_submodel!(child2, :receiver, MockNode;
- inbox=(; in=Int[]),
- )
- connect!(child1, sender_ref.out, self.out)
- connect!(child2, self.in, receiver_ref.in)
- node1_ref = add_submodel!(parent, :child1, child1)
- node2_ref = add_submodel!(parent, :child2, child2)
- connect!(parent, node1_ref.out, node2_ref.in)
- model = compile_devs(parent)
- # Get the assigned integer IDs for the deepest atomics
- sender_id = model.path_to_id["parent.child1.sender"]
- receiver_id = model.path_to_id["parent.child2.receiver"]
- @test haskey(model.couplings, (sender_id, :out))
- @test routes_to(model, sender_id, :out, receiver_id, :in)
- end
|