test_connections.jl 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. function routes_to(model, source_id::Int, source_port::Symbol, target_id::Int, target_port::Symbol)
  2. source_key = (source_id, source_port)
  3. if !haskey(model.couplings, source_key)
  4. return false
  5. end
  6. targets = model.couplings[source_key]
  7. return any(t -> t[1] == target_id && t[2] == target_port, targets)
  8. end
  9. @testset "Self Loops" begin
  10. top = CoupledDEVS(:TopModel)
  11. add_in_port!(top, :in)
  12. add_out_port!(top, :out)
  13. forwarder_ref = add_submodel!(top, :forwarder, MockNode;
  14. inbox=(; in=Int[]),
  15. out_ports=(; out=Int),
  16. forward=true
  17. )
  18. connect!(top, self.out, self.in)
  19. @test_throws IllegalCouplingError compile_devs(top)
  20. empty!(top.couplings)
  21. connect!(top, forwarder_ref.out, forwarder_ref.in)
  22. @test_throws IllegalCouplingError compile_devs(top)
  23. end
  24. @testset "Static Cyclic Couplings" begin
  25. top = CoupledDEVS(:Top)
  26. nodeA_ref = add_submodel!(top, :NodeA, MockNode;
  27. inbox=(; in=Int[]),
  28. out_ports=(; out=Int),
  29. make_out=true, ta=1.0
  30. )
  31. nodeB_ref = add_submodel!(top, :NodeB, MockNode;
  32. inbox=(; in=Int[]),
  33. out_ports=(; out=Int),
  34. make_out=true,
  35. )
  36. connect!(top, nodeA_ref.out, nodeB_ref.in)
  37. connect!(top, nodeB_ref.out, nodeA_ref.in)
  38. model = compile_devs(top)
  39. id_A = model.path_to_id["Top.NodeA"]
  40. id_B = model.path_to_id["Top.NodeB"]
  41. # Check A -> B exists
  42. @test haskey(model.couplings, (id_A, :out))
  43. @test routes_to(model, id_A, :out, id_B, :in)
  44. # @test (id_B, :in) in model.couplings[(id_A, :out)]
  45. # Check B -> A exists
  46. @test haskey(model.couplings, (id_B, :out))
  47. @test routes_to(model, id_B, :out, id_A, :in)
  48. # @test (id_A, :in) in model.couplings[(id_B, :out)]
  49. end
  50. @testset "Atomic Input Couplings" begin
  51. top = CoupledDEVS(:top)
  52. add_in_port!(top, :in)
  53. add_out_port!(top, :out)
  54. inner = CoupledDEVS(:inner)
  55. add_in_port!(inner, :in)
  56. add_out_port!(inner, :out)
  57. atomic_ref1 = add_submodel!(top, :atomic1, MockNode;
  58. inbox=(; in=Int[]),
  59. )
  60. atomic_ref2 = add_submodel!(top, :atomic2, MockNode;
  61. inbox=(; in=Int[]),
  62. out_ports=(; out=Int),
  63. make_out=true
  64. )
  65. inner_ref = add_submodel!(top, :inner, inner)
  66. # atomic in -> atomic in
  67. connect!(top, atomic_ref1.in, atomic_ref2.in)
  68. @test_throws IllegalCouplingError compile_devs(top)
  69. empty!(top.couplings)
  70. # atomic in -> atomic out
  71. connect!(top, atomic_ref1.in, atomic_ref2.out)
  72. @test_throws IllegalCouplingError compile_devs(top)
  73. empty!(top.couplings)
  74. # atomic in -> coupled in
  75. connect!(top, atomic_ref1.in, inner_ref.in)
  76. @test_throws IllegalCouplingError compile_devs(top)
  77. empty!(top.couplings)
  78. # atomic in -> coupled out
  79. connect!(top, atomic_ref1.in, inner_ref.out)
  80. @test_throws IllegalCouplingError compile_devs(top)
  81. empty!(top.couplings)
  82. # atomic in -> parent coupled in
  83. connect!(top, atomic_ref1.in, self.in)
  84. @test_throws IllegalCouplingError compile_devs(top)
  85. empty!(top.couplings)
  86. # atomic in -> parent coupled out
  87. connect!(top, atomic_ref1.in, self.out)
  88. @test_throws IllegalCouplingError compile_devs(top)
  89. empty!(top.couplings)
  90. end
  91. @testset "Atomic Output Couplings" begin
  92. top = CoupledDEVS(:top)
  93. add_in_port!(top, :in)
  94. add_out_port!(top, :out)
  95. inner = CoupledDEVS(:InnerModel)
  96. add_in_port!(inner, :in)
  97. add_out_port!(inner, :out)
  98. atomic_ref1 = add_submodel!(top, :atomic1, MockNode;
  99. out_ports=(; out=Int),
  100. make_out=true
  101. )
  102. atomic_ref2 = add_submodel!(top, :atomic2, MockNode;
  103. inbox=(; in=Int[]),
  104. out_ports=(; out=Int),
  105. make_out=true
  106. )
  107. inner_ref = add_submodel!(top, :inner, inner)
  108. # HAPPY PATHS
  109. # atomic out -> atomic in
  110. connect!(top, atomic_ref1.out, atomic_ref2.in)
  111. model = compile_devs(top)
  112. atomic1_id = model.path_to_id["top.atomic1"]
  113. atomic2_id = model.path_to_id["top.atomic2"]
  114. @test haskey(model.couplings, (atomic1_id, :out))
  115. @test routes_to(model, atomic1_id, :out, atomic2_id, :in)
  116. empty!(top.couplings)
  117. # atomic out -> coupled in
  118. connect!(top, atomic_ref1.out, inner_ref.in)
  119. model = compile_devs(top)
  120. @test model !== nothing
  121. empty!(top.couplings)
  122. # atomic out -> parent coupled out
  123. connect!(top, atomic_ref1.out, self.out)
  124. model = compile_devs(top)
  125. @test model !== nothing
  126. empty!(top.couplings)
  127. # SAD
  128. # atomic out -> atomic out
  129. connect!(top, atomic_ref1.out, atomic_ref2.out)
  130. @test_throws IllegalCouplingError compile_devs(top)
  131. empty!(top.couplings)
  132. # atomic out -> coupled out
  133. connect!(top, atomic_ref1.out, inner_ref.out)
  134. @test_throws IllegalCouplingError compile_devs(top)
  135. empty!(top.couplings)
  136. # atomic out -> parent coupled in
  137. connect!(top, atomic_ref1.out, self.in)
  138. @test_throws IllegalCouplingError compile_devs(top)
  139. empty!(top.couplings)
  140. end
  141. @testset "Static Flatten Connection" begin
  142. parent = CoupledDEVS(:parent)
  143. child1 = CoupledDEVS(:child1)
  144. add_out_port!(child1, :out)
  145. child2 = CoupledDEVS(:child2)
  146. add_in_port!(child2, :in)
  147. sender_ref = add_submodel!(child1, :sender, MockNode;
  148. out_ports=(; out=Int),
  149. make_out=true, ta=1.0
  150. )
  151. receiver_ref = add_submodel!(child2, :receiver, MockNode;
  152. inbox=(; in=Int[]),
  153. )
  154. connect!(child1, sender_ref.out, self.out)
  155. connect!(child2, self.in, receiver_ref.in)
  156. node1_ref = add_submodel!(parent, :child1, child1)
  157. node2_ref = add_submodel!(parent, :child2, child2)
  158. connect!(parent, node1_ref.out, node2_ref.in)
  159. model = compile_devs(parent)
  160. # Get the assigned integer IDs for the deepest atomics
  161. sender_id = model.path_to_id["parent.child1.sender"]
  162. receiver_id = model.path_to_id["parent.child2.receiver"]
  163. @test haskey(model.couplings, (sender_id, :out))
  164. @test routes_to(model, sender_id, :out, receiver_id, :in)
  165. end