| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- julia_test_file = "test/traces/julia.csv"
- @testset "Unconnected Output Port" begin
- top = CoupledDEVS(:top)
- # Sender produces output, but it is NEVER connected to anything!
- sender_ref = add_submodel!(top, :sender, MockNode;
- out_ports=(; out=Int), ta=1.0, make_out=true
- )
- # Compile and run
- model = compile_devs(top; logging=julia_test_file)
- simulate_devs!(model, 2.0)
- test_trace_equivalence(julia_test_file, "test/traces/UnconnectedPort.csv")
- sender = model[model.path_to_id["top.sender"]]
- # Prove the sender successfully generated the output and transitioned anyway
- @test sender.n_outputs == 1
- @test sender.n_internal == 1
- end
- @testset "Pass-Through Test" begin
- top = CoupledDEVS(:Top)
- sender_ref = add_submodel!(top, :Sender, MockNode;
- out_ports=(; out=Int),
- make_out=true, ta=1.0
- )
- forwarder_ref = add_submodel!(top, :Forwarder, MockNode;
- inbox=(; in=Int[]),
- out_ports=(; out=Int),
- forward=true, ta=1.0
- )
- receiver_ref = add_submodel!(top, :Receiver, MockNode;
- inbox=(; in=Int[]),
- )
- connect!(top, sender_ref.out, forwarder_ref.in)
- connect!(top, forwarder_ref.out, receiver_ref.in)
- model = compile_devs(top; logging=julia_test_file)
- simulate_devs!(model, 2.0)
- test_trace_equivalence(julia_test_file, "test/traces/PassThrough.csv")
- forwarder = model[model.path_to_id["Top.Forwarder"]]
- @test forwarder.n_external == 1
- @test length(forwarder.inbox_log) == 1
- @test typeof(forwarder.inbox_log[:in][1]) == Int
- @test forwarder.inbox_log[:in][1] == 42
- @test forwarder.n_internal == 1
- @test forwarder.forward_msg === nothing
- receiver = model[model.path_to_id["Top.Receiver"]]
- @test receiver.n_external == 1
- @test length(receiver.inbox_log) == 1
- @test typeof(receiver.inbox_log[:in][1]) == Int
- @test receiver.inbox_log[:in][1] == 42
- end
- @testset "Cyclic Couplings" begin
- top = CoupledDEVS(:Top)
- nodeA_ref = add_submodel!(top, :NodeA, MockNode;
- inbox=(; in=Int[]),
- out_ports=(; out=Int),
- forward=true, ta=1.0, forward_msg=1
- )
- nodeB_ref = add_submodel!(top, :NodeB, MockNode;
- inbox=(; in=Int[]),
- out_ports=(; out=Int),
- forward=true, ta=1.0
- )
- connect!(top, nodeA_ref.out, nodeB_ref.in)
- connect!(top, nodeB_ref.out, nodeA_ref.in)
- model = compile_devs(top; logging=julia_test_file)
- simulate_devs!(model, 12.0)
- test_trace_equivalence(julia_test_file, "test/traces/CyclicCoupling.csv")
- nodeA = model[model.path_to_id["Top.NodeA"]]
- @test nodeA.n_internal == 6
- @test nodeA.n_external == 6
- nodeB = model[model.path_to_id["Top.NodeB"]]
- @test nodeB.n_external == 6
- end
- @testset "Fan-In Routing Test (Simultaneous Arrival)" begin
- top = CoupledDEVS(:Top)
- sender_ref1 = add_submodel!(top, :Sender1, MockNode;
- out_ports=(; out=Int),
- ta=1.0, make_out=true
- )
- sender_ref2 = add_submodel!(top, :Sender2, MockNode;
- out_ports=(; out=Int),
- ta=1.0, make_out=true
- )
- receiver_ref = add_submodel!(top, :Receiver, MockNode;
- inbox=(; in=Int[]),
- )
- connect!(top, sender_ref1.out, receiver_ref.in)
- connect!(top, sender_ref2.out, receiver_ref.in)
- model = compile_devs(top; logging=julia_test_file)
- simulate_devs!(model, 2.0)
- test_trace_equivalence(julia_test_file, "test/traces/FanIn.csv")
- receiver = model[model.path_to_id["Top.Receiver"]]
- @test receiver.n_internal == 0
- @test receiver.n_external == 1
- @test receiver.n_confluent == 0
- @test length(receiver.inbox_log[:in]) == 2
- end
- @testset "Fan-Out Routing Test" begin
- top = CoupledDEVS(:Top)
- sender_ref = add_submodel!(top, :Sender, MockNode;
- out_ports=(; out=Int),
- make_out=true, ta=1.0
- )
- receiver_ref1 = add_submodel!(top, :Receiver1, MockNode;
- inbox=(; in=Int[]),
- )
- receiver_ref2 = add_submodel!(top, :Receiver2, MockNode;
- inbox=(; in=Int[]),
- )
- connect!(top, sender_ref.out, receiver_ref1.in)
- connect!(top, sender_ref.out, receiver_ref2.in)
- model = compile_devs(top; logging=julia_test_file)
- simulate_devs!(model)
- test_trace_equivalence(julia_test_file, "test/traces/FanOut.csv")
- receiver1 = model[model.path_to_id["Top.Receiver1"]]
- receiver2 = model[model.path_to_id["Top.Receiver2"]]
- @test receiver1.n_external == 1
- @test receiver2.n_external == 1
- @test length(receiver1.inbox_log) == 1
- @test length(receiver2.inbox_log) == 1
- end
- @testset "Flattened Connection Routing" 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)
- node_ref1 = add_submodel!(parent, :child1, child1)
- node_ref2 = add_submodel!(parent, :child2, child2)
- connect!(parent, node_ref1.out, node_ref2.in)
- model = compile_devs(parent; logging=julia_test_file)
- simulate_devs!(model)
- test_trace_equivalence(julia_test_file, "test/traces/FlattenedConnection.csv")
- receiver = model[model.path_to_id["parent.child2.receiver"]]
- @test receiver.n_external == 1
- @test length(receiver.inbox_log) == 1
- @test typeof(receiver.inbox_log[:in][1]) == Int
- @test receiver.inbox_log[:in][1] == 42
- end
- @testset "Complex Bag Semantics (Multi-Port)" begin
- top = CoupledDEVS(:top)
- sA = add_submodel!(top, :sA, MockNode; out_ports=(; out=Int), ta=2.0, make_out=true)
- sB = add_submodel!(top, :sB, MockNode; out_ports=(; out=Int), ta=2.0, make_out=true)
- # Receiver with TWO input ports
- rec = add_submodel!(top, :rec, MockNode;
- inbox=(; in_A=Int[], in_B=Int[])
- )
- connect!(top, sA.out, rec.in_A)
- connect!(top, sB.out, rec.in_B)
- model = compile_devs(top; logging=julia_test_file)
- simulate_devs!(model, 3.0)
- test_trace_equivalence(julia_test_file, "test/traces/ComplexBag.csv")
- node = model[model.path_to_id["top.rec"]]
- @test node.n_external == 1 # Only ONE external transition is fired for both!
- # Ensure both ports have data in the bag
- @test length(node.inbox_log[:in_A]) == 1
- @test length(node.inbox_log[:in_B]) == 1
- end
|