test_transitions.jl 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. julia_test_file = "test/traces/julia.csv"
  2. @testset "Transient State (ta = 0.0)" begin
  3. top = CoupledDEVS(:top)
  4. sender_ref = add_submodel!(top, :sender, MockNode;
  5. out_ports=(; out=Int), make_out=true, ta=1.0
  6. )
  7. transient_node = add_submodel!(top, :transient, MockNode;
  8. inbox=(; in=Int[]), out_ports=(; out=Int), ta=0.0, forward=true
  9. )
  10. connect!(top, sender_ref.out, transient_node.in)
  11. model = compile_devs(top)
  12. simulate_devs!(model, 2.0)
  13. node = model[model.path_to_id["top.transient"]]
  14. # Proves it received the message, then instantly fired internally without time passing
  15. @test node.exec_order == [:ta, :external, :ta, :output, :internal, :ta]
  16. @test abmtime(model) == 1.0 # Global clock should NOT have advanced past the trigger time
  17. end
  18. @testset "Test Order Output-Transition" begin
  19. top = CoupledDEVS(:top)
  20. sender_ref = add_submodel!(top, :sender, MockNode;
  21. out_ports=(; out=Int),
  22. make_out=true, ta=2.0
  23. )
  24. receiver_ref = add_submodel!(top, :receiver, MockNode;
  25. inbox=(; in=Int[]),
  26. )
  27. connect!(top, sender_ref.out, receiver_ref.in)
  28. model = compile_devs(top)
  29. simulate_devs!(model)
  30. sender = model[model.path_to_id["top.sender"]]
  31. @test sender.n_outputs == 1
  32. @test sender.n_internal == 1
  33. @test sender.n_external == 0
  34. @test sender.n_confluent == 0
  35. @test sender.exec_order[1:3] == [:ta, :output, :internal]
  36. end
  37. @testset "Obsolete Event Purging" begin
  38. top = CoupledDEVS(:top)
  39. # Fast sender, fires every 1.0 seconds
  40. sender = add_submodel!(top, :sender, MockNode; out_ports=(; out=Int), ta=1.0, cycles=5, make_out=true)
  41. # Slow receiver, wants to fire at 10.0 seconds
  42. rec = add_submodel!(top, :rec, MockNode; inbox=(; in=Int[]), ta=4.0)
  43. connect!(top, sender.out, rec.in)
  44. model = compile_devs(top)
  45. simulate_devs!(model, 11.0)
  46. node = model[model.path_to_id["top.rec"]]
  47. @test node.n_external == 5
  48. @test node.n_internal == 1
  49. end
  50. @testset "Internal Transition Test" begin
  51. top = CoupledDEVS(:top)
  52. add_submodel!(top, :receiver, MockNode;
  53. inbox=(; in=Int[]),
  54. ta=2.0
  55. )
  56. model = compile_devs(top; logging=julia_test_file)
  57. simulate_devs!(model)
  58. test_trace_equivalence(julia_test_file, "test/traces/Internal.csv")
  59. receiver = model[model.path_to_id["top.receiver"]]
  60. @test receiver.n_internal == 1
  61. @test receiver.n_external == 0
  62. @test receiver.n_confluent == 0
  63. end
  64. @testset "External Transition Test" begin
  65. top = CoupledDEVS(:top)
  66. sender_ref = add_submodel!(top, :sender, MockNode;
  67. out_ports=(; out=Int),
  68. ta=1.0, make_out=true
  69. )
  70. receiver_ref = add_submodel!(top, :receiver, MockNode;
  71. inbox=(; in=Int[]),
  72. )
  73. connect!(top, sender_ref.out, receiver_ref.in)
  74. model = compile_devs(top; logging=julia_test_file)
  75. simulate_devs!(model)
  76. test_trace_equivalence(julia_test_file, "test/traces/External.csv")
  77. sender = model[model.path_to_id["top.sender"]]
  78. @test sender.n_internal == 1
  79. @test sender.n_external == 0
  80. @test sender.n_confluent == 0
  81. receiver = model[model.path_to_id["top.receiver"]]
  82. @test receiver.n_internal == 0
  83. @test receiver.n_external == 1
  84. @test receiver.n_confluent == 0
  85. end
  86. @testset "Elapsed Time Interruption" begin
  87. top = CoupledDEVS(:top)
  88. sender_ref = add_submodel!(top, :sender, MockNode; out_ports=(; out=Int), ta=1.5, make_out=true)
  89. receiver_ref = add_submodel!(top, :receiver, MockNode; inbox=(; in=Int[]), ta=5.0)
  90. connect!(top, sender_ref.out, receiver_ref.in)
  91. model = compile_devs(top; logging=julia_test_file)
  92. simulate_devs!(model, 2.0)
  93. test_trace_equivalence(julia_test_file, "test/traces/ElapsedTimeInterruption.csv")
  94. receiver = model[model.path_to_id["top.receiver"]]
  95. @test receiver.n_external == 1
  96. @test receiver.last_e == 1.5
  97. end
  98. @testset "Elapsed Time Reset (Multiple Interruptions)" begin
  99. top = CoupledDEVS(:top)
  100. s1 = add_submodel!(top, :s1, MockNode; out_ports=(; out=Int), ta=3.0, make_out=true)
  101. s2 = add_submodel!(top, :s2, MockNode; out_ports=(; out=Int), ta=5.0, make_out=true)
  102. rec = add_submodel!(top, :rec, MockNode; inbox=(; in=Int[]), ta=10.0)
  103. connect!(top, s1.out, rec.in)
  104. connect!(top, s2.out, rec.in)
  105. model = compile_devs(top; logging=julia_test_file)
  106. simulate_devs!(model, 4.0)
  107. test_trace_equivalence(julia_test_file, "test/traces/ElapsedTimeReset1.csv")
  108. @test model[model.path_to_id["top.rec"]].last_e == 3.0
  109. simulate_devs!(model, 6.0)
  110. test_trace_equivalence(julia_test_file, "test/traces/ElapsedTimeReset2.csv")
  111. @test model[model.path_to_id["top.rec"]].last_e == 2.0
  112. end
  113. @testset "Confluent Transition Test" begin
  114. top = CoupledDEVS(:top)
  115. sender_ref = add_submodel!(top, :sender, MockNode;
  116. out_ports=(; out=Int),
  117. ta=2.0, make_out=true
  118. )
  119. receiver_ref = add_submodel!(top, :receiver, MockNode;
  120. inbox=(; in=Int[]),
  121. ta=2.0
  122. )
  123. connect!(top, sender_ref.out, receiver_ref.in)
  124. model = compile_devs(top; logging=julia_test_file)
  125. simulate_devs!(model)
  126. test_trace_equivalence(julia_test_file, "test/traces/Confluent.csv")
  127. sender = model[model.path_to_id["top.sender"]]
  128. @test sender.n_internal == 1
  129. @test sender.n_external == 0
  130. @test sender.n_confluent == 0
  131. receiver = model[model.path_to_id["top.receiver"]]
  132. @test receiver.n_internal == 1
  133. @test receiver.n_external == 1
  134. @test receiver.n_confluent == 1
  135. end
  136. @testset "Nearly Confluent Transition Test" begin
  137. top = CoupledDEVS(:top)
  138. sender_ref = add_submodel!(top, :sender, MockNode;
  139. out_ports=(; out=Int),
  140. ta=1.999, make_out=true
  141. )
  142. receiver_ref = add_submodel!(top, :receiver, MockNode;
  143. inbox=(; in=Int[]),
  144. ta=2.000
  145. )
  146. connect!(top, sender_ref.out, receiver_ref.in)
  147. model = compile_devs(top; logging=julia_test_file)
  148. simulate_devs!(model)
  149. test_trace_equivalence(julia_test_file, "test/traces/NearlyConfluent.csv")
  150. sender = model[model.path_to_id["top.sender"]]
  151. @test sender.n_internal == 1
  152. @test sender.n_external == 0
  153. @test sender.n_confluent == 0
  154. receiver = model[model.path_to_id["top.receiver"]]
  155. @test receiver.n_internal == 1
  156. @test receiver.n_external == 1
  157. @test receiver.n_confluent == 0
  158. end
  159. @testset "Confluent Output Test" begin
  160. top = CoupledDEVS(:top)
  161. sender1_ref = add_submodel!(top, :sender1, MockNode;
  162. out_ports=(; out=Int),
  163. ta=2.0, make_out=true
  164. )
  165. sender2_ref = add_submodel!(top, :sender2, MockNode;
  166. inbox=(; in=Int[]),
  167. out_ports=(; out=Int),
  168. ta=2.0, make_out=true
  169. )
  170. receiver_ref = add_submodel!(top, :receiver, MockNode;
  171. inbox=(; in=Int[]),
  172. )
  173. connect!(top, sender1_ref.out, sender2_ref.in)
  174. connect!(top, sender2_ref.out, receiver_ref.in)
  175. model = compile_devs(top; logging=julia_test_file)
  176. simulate_devs!(model)
  177. test_trace_equivalence(julia_test_file, "test/traces/ConfluentOutput.csv")
  178. sender1 = model[model.path_to_id["top.sender1"]]
  179. @test sender1.n_internal == 1
  180. @test sender1.n_external == 0
  181. @test sender1.n_confluent == 0
  182. @test sender1.n_outputs == 1
  183. sender2 = model[model.path_to_id["top.sender2"]]
  184. @test sender2.n_internal == 1
  185. @test sender2.n_external == 1
  186. @test sender2.n_confluent == 1
  187. @test sender2.n_outputs == 1
  188. receiver = model[model.path_to_id["top.receiver"]]
  189. @test receiver.n_internal == 0
  190. @test receiver.n_external == 1
  191. @test receiver.n_confluent == 0
  192. end