roby 0.8.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (644) hide show
  1. checksums.yaml +7 -0
  2. data/.deep-cover.rb +3 -0
  3. data/.gitattributes +1 -0
  4. data/.gitignore +24 -0
  5. data/.simplecov +10 -0
  6. data/.travis.yml +17 -0
  7. data/.yardopts +4 -0
  8. data/Gemfile +15 -0
  9. data/README.md +11 -0
  10. data/Rakefile +47 -177
  11. data/benchmark/{alloc_misc.rb → attic/alloc_misc.rb} +2 -2
  12. data/benchmark/{discovery_latency.rb → attic/discovery_latency.rb} +19 -19
  13. data/benchmark/{garbage_collection.rb → attic/garbage_collection.rb} +9 -9
  14. data/benchmark/{genom.rb → attic/genom.rb} +0 -0
  15. data/benchmark/attic/transactions.rb +62 -0
  16. data/benchmark/plan_basic_operations.rb +28 -0
  17. data/benchmark/relations/graph.rb +63 -0
  18. data/benchmark/ruby/identity.rb +18 -0
  19. data/benchmark/ruby/set_intersect_vs_hash_merge.rb +39 -0
  20. data/benchmark/ruby/yield_vs_block.rb +35 -0
  21. data/benchmark/run +5 -0
  22. data/benchmark/synthetic_plan_modifications_with_transactions.rb +79 -0
  23. data/benchmark/transactions.rb +99 -51
  24. data/bin/roby +38 -197
  25. data/bin/roby-display +14 -0
  26. data/bin/roby-log +3 -176
  27. data/doc/guide/{src → attic}/abstraction/achieve_with.page +1 -1
  28. data/doc/guide/{src → attic}/abstraction/forwarding.page +1 -1
  29. data/doc/guide/{src → attic}/abstraction/hierarchy.page +1 -1
  30. data/doc/guide/{src → attic}/abstraction/index.page +1 -1
  31. data/doc/guide/{src → attic}/abstraction/task_models.page +1 -1
  32. data/doc/guide/{overview.rdoc → attic/cycle/api_overview.rdoc} +6 -1
  33. data/doc/guide/{src → attic}/cycle/cycle-overview.png +0 -0
  34. data/doc/guide/{src → attic}/cycle/cycle-overview.svg +0 -0
  35. data/doc/guide/attic/cycle/error_handling.page +98 -0
  36. data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.png +0 -0
  37. data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.svg +0 -0
  38. data/doc/guide/{src/cycle/error_handling.page → attic/cycle/error_sources.page} +46 -89
  39. data/doc/guide/{src → attic}/cycle/garbage_collection.page +1 -1
  40. data/doc/guide/{src → attic}/cycle/index.page +1 -1
  41. data/doc/guide/{src → attic}/cycle/propagation.page +11 -1
  42. data/doc/guide/{src → attic}/cycle/propagation_diamond.png +0 -0
  43. data/doc/guide/{src → attic}/cycle/propagation_diamond.svg +0 -0
  44. data/doc/guide/attic/plans/building_plans.page +89 -0
  45. data/doc/guide/attic/plans/code.page +192 -0
  46. data/doc/guide/{src/basics → attic/plans}/events.page +3 -4
  47. data/doc/guide/attic/plans/index.page +7 -0
  48. data/doc/guide/{plan_modifications.rdoc → attic/plans/plan_modifications.rdoc} +5 -3
  49. data/doc/guide/{src/basics → attic/plans}/plan_objects.page +2 -1
  50. data/doc/guide/attic/plans/querying_plans.page +5 -0
  51. data/doc/guide/{src/basics → attic/plans}/tasks.page +20 -20
  52. data/doc/guide/config.yaml +7 -4
  53. data/doc/guide/ext/extended_menu.rb +29 -0
  54. data/doc/guide/ext/init.rb +6 -0
  55. data/doc/guide/ext/rdoc_links.rb +7 -6
  56. data/doc/guide/src/advanced_concepts/history.page +5 -0
  57. data/doc/guide/src/advanced_concepts/index.page +11 -0
  58. data/doc/guide/src/advanced_concepts/recognizing_patterns.page +83 -0
  59. data/doc/guide/src/advanced_concepts/scheduling.page +87 -0
  60. data/doc/guide/src/advanced_concepts/transactions.page +5 -0
  61. data/doc/guide/src/advanced_concepts/unreachability.page +42 -0
  62. data/doc/guide/src/base.template +96 -0
  63. data/doc/guide/src/basics_shell_header.txt +5 -7
  64. data/doc/guide/src/building/action_coordination.page +96 -0
  65. data/doc/guide/src/building/actions.page +124 -0
  66. data/doc/guide/src/building/file_layout.page +71 -0
  67. data/doc/guide/src/building/index.page +50 -0
  68. data/doc/guide/src/building/patterns.page +86 -0
  69. data/doc/guide/src/building/patterns_forwarding.png +0 -0
  70. data/doc/guide/src/building/patterns_forwarding.svg +277 -0
  71. data/doc/guide/src/building/runtime.page +95 -0
  72. data/doc/guide/src/building/task_models.page +94 -0
  73. data/doc/guide/src/building/tasks.page +284 -0
  74. data/doc/guide/src/concepts/error_handling.page +100 -0
  75. data/doc/guide/src/concepts/exception_propagation.png +0 -0
  76. data/doc/guide/src/concepts/exception_propagation.svg +445 -0
  77. data/doc/guide/src/concepts/execution.page +85 -0
  78. data/doc/guide/src/concepts/execution.png +0 -0
  79. data/doc/guide/src/concepts/execution.svg +573 -0
  80. data/doc/guide/src/concepts/execution_cycle.png +0 -0
  81. data/doc/guide/src/concepts/garbage_collection.page +57 -0
  82. data/doc/guide/src/concepts/index.page +27 -0
  83. data/doc/guide/src/concepts/plans.page +101 -0
  84. data/doc/guide/src/concepts/policy.page +31 -0
  85. data/doc/guide/src/concepts/reactor.page +61 -0
  86. data/doc/guide/src/concepts/simple_plan_example.png +0 -0
  87. data/doc/guide/src/concepts/simple_plan_example.svg +376 -0
  88. data/doc/guide/src/default.template +9 -74
  89. data/doc/guide/src/event_relations/forward.page +71 -0
  90. data/doc/guide/src/event_relations/index.page +12 -0
  91. data/doc/guide/src/event_relations/scheduling_constraints.page +43 -0
  92. data/doc/guide/src/event_relations/signal.page +55 -0
  93. data/doc/guide/src/event_relations/temporal_constraints.page +77 -0
  94. data/doc/guide/src/htmldoc.metainfo +21 -8
  95. data/doc/guide/src/index.page +8 -3
  96. data/doc/guide/src/{introduction/install.page → installation/index.page} +37 -25
  97. data/doc/guide/src/installation/publications.page +14 -0
  98. data/doc/guide/src/{introduction → installation}/videos.page +14 -7
  99. data/doc/guide/src/interacting/index.page +16 -0
  100. data/doc/guide/src/interacting/run.page +33 -0
  101. data/doc/guide/src/interacting/shell.page +95 -0
  102. data/doc/guide/src/plugins/creating_plugins.page +72 -0
  103. data/doc/guide/src/plugins/index.page +27 -5
  104. data/doc/guide/src/plugins/{fault_tolerance.page → standard_plugins/fault_tolerance.page} +2 -2
  105. data/doc/guide/src/plugins/standard_plugins/index.page +11 -0
  106. data/doc/guide/src/plugins/{subsystems.page → standard_plugins/subsystems.page} +2 -2
  107. data/doc/guide/src/style_screen.css +687 -0
  108. data/doc/guide/src/task_relations/dependency.page +107 -0
  109. data/doc/guide/src/task_relations/executed_by.page +77 -0
  110. data/doc/guide/src/task_relations/index.page +12 -0
  111. data/doc/guide/src/task_relations/new_relations.page +119 -0
  112. data/doc/guide/src/task_relations/planned_by.page +46 -0
  113. data/doc/guide/src/tutorial/app.page +117 -0
  114. data/doc/guide/src/{basics → tutorial}/code_examples.page +6 -5
  115. data/doc/guide/src/{basics → tutorial}/dry.page +15 -15
  116. data/doc/guide/src/{basics → tutorial}/errors.page +43 -68
  117. data/doc/guide/src/tutorial/events.page +195 -0
  118. data/doc/guide/src/{basics → tutorial}/hierarchy.page +53 -52
  119. data/doc/guide/src/tutorial/index.page +13 -0
  120. data/doc/guide/src/tutorial/log_replay/goForward_1.png +0 -0
  121. data/doc/guide/src/tutorial/log_replay/goForward_2.png +0 -0
  122. data/doc/guide/src/tutorial/log_replay/goForward_3.png +0 -0
  123. data/doc/guide/src/{basics → tutorial}/log_replay/goForward_4.png +0 -0
  124. data/doc/guide/src/tutorial/log_replay/goForward_5.png +0 -0
  125. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_1.png +0 -0
  126. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_2.png +0 -0
  127. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_3.png +0 -0
  128. data/doc/guide/src/tutorial/log_replay/moveto_code_error.png +0 -0
  129. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_1.png +0 -0
  130. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_2.png +0 -0
  131. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_3.png +0 -0
  132. data/doc/guide/src/tutorial/log_replay/plan_repair_4.png +0 -0
  133. data/doc/guide/src/tutorial/log_replay/roby_log_main_window.png +0 -0
  134. data/doc/guide/src/{basics → tutorial}/log_replay/roby_log_relation_window.png +0 -0
  135. data/doc/guide/src/{basics → tutorial}/log_replay/roby_replay_event_representation.png +0 -0
  136. data/doc/guide/src/tutorial/relations_display.page +153 -0
  137. data/doc/guide/src/{basics → tutorial}/roby_cycle_overview.png +0 -0
  138. data/doc/guide/src/tutorial/shell.page +121 -0
  139. data/doc/guide/src/{basics → tutorial}/summary.page +1 -1
  140. data/doc/guide/src/tutorial/tasks.page +374 -0
  141. data/lib/roby.rb +102 -47
  142. data/lib/roby/actions.rb +17 -0
  143. data/lib/roby/actions/action.rb +80 -0
  144. data/lib/roby/actions/interface.rb +45 -0
  145. data/lib/roby/actions/library.rb +23 -0
  146. data/lib/roby/actions/models/action.rb +224 -0
  147. data/lib/roby/actions/models/coordination_action.rb +58 -0
  148. data/lib/roby/actions/models/interface.rb +22 -0
  149. data/lib/roby/actions/models/interface_base.rb +294 -0
  150. data/lib/roby/actions/models/library.rb +12 -0
  151. data/lib/roby/actions/models/method_action.rb +90 -0
  152. data/lib/roby/actions/task.rb +114 -0
  153. data/lib/roby/and_generator.rb +125 -0
  154. data/lib/roby/app.rb +2795 -829
  155. data/lib/roby/app/autotest_console_reporter.rb +138 -0
  156. data/lib/roby/app/base.rb +21 -0
  157. data/lib/roby/app/cucumber.rb +2 -0
  158. data/lib/roby/app/cucumber/controller.rb +439 -0
  159. data/lib/roby/app/cucumber/helpers.rb +280 -0
  160. data/lib/roby/app/cucumber/world.rb +32 -0
  161. data/lib/roby/app/debug.rb +136 -0
  162. data/lib/roby/app/gen.rb +2 -0
  163. data/lib/roby/app/rake.rb +178 -38
  164. data/lib/roby/app/robot_config.rb +9 -0
  165. data/lib/roby/app/robot_names.rb +115 -0
  166. data/lib/roby/app/run.rb +3 -2
  167. data/lib/roby/app/scripts.rb +72 -0
  168. data/lib/roby/app/scripts/autotest.rb +173 -0
  169. data/lib/roby/app/scripts/display.rb +2 -0
  170. data/lib/roby/app/scripts/restart.rb +52 -0
  171. data/lib/roby/app/scripts/results.rb +17 -8
  172. data/lib/roby/app/scripts/run.rb +155 -24
  173. data/lib/roby/app/scripts/shell.rb +147 -62
  174. data/lib/roby/app/scripts/test.rb +107 -22
  175. data/lib/roby/app/test_reporter.rb +74 -0
  176. data/lib/roby/app/test_server.rb +159 -0
  177. data/lib/roby/app/vagrant.rb +47 -0
  178. data/lib/roby/backports.rb +16 -0
  179. data/lib/roby/cli/display.rb +190 -0
  180. data/lib/roby/cli/exceptions.rb +17 -0
  181. data/lib/roby/cli/gen/actions/class.rb +5 -0
  182. data/lib/roby/cli/gen/actions/test.rb +6 -0
  183. data/lib/roby/cli/gen/app/.yardopts +6 -0
  184. data/lib/roby/cli/gen/app/README.md +28 -0
  185. data/lib/roby/cli/gen/app/Rakefile +15 -0
  186. data/{app → lib/roby/cli/gen/app}/config/app.yml +29 -39
  187. data/lib/roby/cli/gen/app/models/.gitattributes +1 -0
  188. data/{app → lib/roby/cli/gen/app/scripts}/controllers/.gitattributes +0 -0
  189. data/{app/data/.gitattributes → lib/roby/cli/gen/app/test/.gitignore} +0 -0
  190. data/lib/roby/cli/gen/class/class.rb +6 -0
  191. data/lib/roby/cli/gen/class/test.rb +7 -0
  192. data/lib/roby/cli/gen/helpers.rb +203 -0
  193. data/lib/roby/cli/gen/module/module.rb +5 -0
  194. data/lib/roby/cli/gen/module/test.rb +6 -0
  195. data/lib/roby/cli/gen/roby_app/config/init.rb +17 -0
  196. data/lib/roby/cli/gen/roby_app/config/robots/robot.rb +40 -0
  197. data/lib/roby/cli/gen/task/class.rb +44 -0
  198. data/lib/roby/cli/gen/task/test.rb +6 -0
  199. data/lib/roby/cli/gen_main.rb +120 -0
  200. data/lib/roby/cli/log.rb +276 -0
  201. data/lib/roby/cli/log/flamegraph.html +499 -0
  202. data/lib/roby/cli/log/flamegraph_renderer.rb +88 -0
  203. data/lib/roby/cli/main.rb +153 -0
  204. data/lib/roby/coordination.rb +60 -0
  205. data/lib/roby/coordination/action_script.rb +25 -0
  206. data/lib/roby/coordination/action_state_machine.rb +125 -0
  207. data/lib/roby/coordination/actions.rb +106 -0
  208. data/lib/roby/coordination/base.rb +145 -0
  209. data/lib/roby/coordination/calculus.rb +40 -0
  210. data/lib/roby/coordination/child.rb +28 -0
  211. data/lib/roby/coordination/event.rb +29 -0
  212. data/lib/roby/coordination/fault_handler.rb +25 -0
  213. data/lib/roby/coordination/fault_handling_task.rb +13 -0
  214. data/lib/roby/coordination/fault_response_table.rb +110 -0
  215. data/lib/roby/coordination/models/action_script.rb +64 -0
  216. data/lib/roby/coordination/models/action_state_machine.rb +224 -0
  217. data/lib/roby/coordination/models/actions.rb +191 -0
  218. data/lib/roby/coordination/models/arguments.rb +55 -0
  219. data/lib/roby/coordination/models/base.rb +176 -0
  220. data/lib/roby/coordination/models/capture.rb +86 -0
  221. data/lib/roby/coordination/models/child.rb +35 -0
  222. data/lib/roby/coordination/models/event.rb +41 -0
  223. data/lib/roby/coordination/models/exceptions.rb +42 -0
  224. data/lib/roby/coordination/models/fault_handler.rb +219 -0
  225. data/lib/roby/coordination/models/fault_response_table.rb +77 -0
  226. data/lib/roby/coordination/models/root.rb +22 -0
  227. data/lib/roby/coordination/models/script.rb +283 -0
  228. data/lib/roby/coordination/models/task.rb +184 -0
  229. data/lib/roby/coordination/models/task_from_action.rb +50 -0
  230. data/lib/roby/coordination/models/task_from_as_plan.rb +33 -0
  231. data/lib/roby/coordination/models/task_from_instanciation_object.rb +31 -0
  232. data/lib/roby/coordination/models/task_from_variable.rb +27 -0
  233. data/lib/roby/coordination/models/task_with_dependencies.rb +48 -0
  234. data/lib/roby/coordination/models/variable.rb +32 -0
  235. data/lib/roby/coordination/script.rb +200 -0
  236. data/lib/roby/coordination/script_instruction.rb +12 -0
  237. data/lib/roby/coordination/task.rb +45 -0
  238. data/lib/roby/coordination/task_base.rb +69 -0
  239. data/lib/roby/coordination/task_script.rb +293 -0
  240. data/lib/roby/coordination/task_state_machine.rb +308 -0
  241. data/lib/roby/decision_control.rb +33 -21
  242. data/lib/roby/distributed_object.rb +76 -0
  243. data/lib/roby/droby.rb +17 -0
  244. data/lib/roby/droby/droby_id.rb +6 -0
  245. data/lib/roby/droby/enable.rb +153 -0
  246. data/lib/roby/droby/event_logger.rb +189 -0
  247. data/lib/roby/droby/event_logging.rb +57 -0
  248. data/lib/roby/droby/exceptions.rb +14 -0
  249. data/lib/roby/droby/identifiable.rb +22 -0
  250. data/lib/roby/droby/logfile.rb +141 -0
  251. data/lib/roby/droby/logfile/client.rb +176 -0
  252. data/lib/roby/droby/logfile/file_format.md +97 -0
  253. data/lib/roby/droby/logfile/index.rb +117 -0
  254. data/lib/roby/droby/logfile/reader.rb +139 -0
  255. data/lib/roby/droby/logfile/server.rb +199 -0
  256. data/lib/roby/droby/logfile/writer.rb +114 -0
  257. data/lib/roby/droby/marshal.rb +264 -0
  258. data/lib/roby/droby/marshallable.rb +12 -0
  259. data/lib/roby/droby/null_event_logger.rb +25 -0
  260. data/lib/roby/droby/object_manager.rb +205 -0
  261. data/lib/roby/droby/peer_id.rb +6 -0
  262. data/lib/roby/droby/plan_rebuilder.rb +373 -0
  263. data/lib/roby/droby/rebuilt_plan.rb +160 -0
  264. data/lib/roby/droby/remote_droby_id.rb +6 -0
  265. data/lib/roby/droby/timepoints.rb +205 -0
  266. data/lib/roby/droby/timepoints_ctf.metadata.erb +101 -0
  267. data/lib/roby/droby/timepoints_ctf.rb +125 -0
  268. data/lib/roby/droby/v5.rb +14 -0
  269. data/lib/roby/droby/v5/builtin.rb +120 -0
  270. data/lib/roby/droby/v5/droby_class.rb +45 -0
  271. data/lib/roby/droby/v5/droby_constant.rb +81 -0
  272. data/lib/roby/droby/v5/droby_dump.rb +1026 -0
  273. data/lib/roby/droby/v5/droby_id.rb +44 -0
  274. data/lib/roby/droby/v5/droby_model.rb +82 -0
  275. data/lib/roby/droby/v5/peer_id.rb +10 -0
  276. data/lib/roby/droby/v5/remote_droby_id.rb +42 -0
  277. data/lib/roby/event.rb +79 -957
  278. data/lib/roby/event_constraints.rb +835 -0
  279. data/lib/roby/event_generator.rb +1047 -0
  280. data/lib/roby/event_structure/causal_link.rb +6 -0
  281. data/lib/roby/event_structure/forwarding.rb +6 -0
  282. data/lib/roby/event_structure/precedence.rb +7 -0
  283. data/lib/roby/event_structure/signal.rb +8 -0
  284. data/lib/roby/event_structure/temporal_constraints.rb +640 -0
  285. data/lib/roby/exceptions.rb +446 -152
  286. data/lib/roby/executable_plan.rb +549 -0
  287. data/lib/roby/execution_engine.rb +1997 -950
  288. data/lib/roby/filter_generator.rb +26 -0
  289. data/lib/roby/gui/chronicle_view.rb +225 -0
  290. data/lib/roby/gui/chronicle_widget.rb +925 -0
  291. data/lib/roby/gui/dot_id.rb +11 -0
  292. data/lib/roby/gui/exception_view.rb +44 -0
  293. data/lib/roby/gui/log_display.rb +273 -0
  294. data/lib/roby/gui/model_views.rb +2 -0
  295. data/lib/roby/gui/model_views/action_interface.rb +53 -0
  296. data/lib/roby/gui/model_views/task.rb +47 -0
  297. data/lib/roby/gui/model_views/task.rhtml +41 -0
  298. data/lib/roby/gui/object_info_view.rb +89 -0
  299. data/lib/roby/gui/plan_dot_layout.rb +427 -0
  300. data/lib/roby/gui/plan_rebuilder_widget.rb +357 -0
  301. data/lib/roby/gui/qt4_toMSecsSinceEpoch.rb +8 -0
  302. data/lib/roby/gui/relations_view.rb +278 -0
  303. data/lib/roby/gui/relations_view/relations.ui +139 -0
  304. data/lib/roby/gui/relations_view/relations_canvas.rb +1088 -0
  305. data/lib/roby/gui/relations_view/relations_config.rb +292 -0
  306. data/lib/roby/gui/relations_view/relations_view.ui +53 -0
  307. data/lib/roby/gui/scheduler_view.css +24 -0
  308. data/lib/roby/gui/scheduler_view.rb +46 -0
  309. data/lib/roby/gui/scheduler_view.rhtml +53 -0
  310. data/lib/roby/gui/stepping.rb +93 -0
  311. data/lib/roby/gui/stepping.ui +181 -0
  312. data/lib/roby/gui/styles.rb +81 -0
  313. data/lib/roby/gui/task_display_configuration.rb +42 -0
  314. data/lib/roby/gui/task_state_at.rb +38 -0
  315. data/lib/roby/hooks.rb +26 -0
  316. data/lib/roby/interface.rb +136 -469
  317. data/lib/roby/interface/async.rb +20 -0
  318. data/lib/roby/interface/async/action_monitor.rb +188 -0
  319. data/lib/roby/interface/async/interface.rb +498 -0
  320. data/lib/roby/interface/async/job_monitor.rb +213 -0
  321. data/lib/roby/interface/async/log.rb +238 -0
  322. data/lib/roby/interface/async/new_job_listener.rb +79 -0
  323. data/lib/roby/interface/async/ui_connector.rb +183 -0
  324. data/lib/roby/interface/client.rb +553 -0
  325. data/lib/roby/interface/command.rb +24 -0
  326. data/lib/roby/interface/command_argument.rb +16 -0
  327. data/lib/roby/interface/command_library.rb +92 -0
  328. data/lib/roby/interface/droby_channel.rb +174 -0
  329. data/lib/roby/interface/exceptions.rb +22 -0
  330. data/lib/roby/interface/interface.rb +655 -0
  331. data/lib/roby/interface/job.rb +47 -0
  332. data/lib/roby/interface/rest.rb +10 -0
  333. data/lib/roby/interface/rest/api.rb +29 -0
  334. data/lib/roby/interface/rest/helpers.rb +24 -0
  335. data/lib/roby/interface/rest/server.rb +212 -0
  336. data/lib/roby/interface/server.rb +154 -0
  337. data/lib/roby/interface/shell_client.rb +468 -0
  338. data/lib/roby/interface/shell_subcommand.rb +24 -0
  339. data/lib/roby/interface/subcommand_client.rb +35 -0
  340. data/lib/roby/interface/tcp.rb +168 -0
  341. data/lib/roby/models/arguments.rb +112 -0
  342. data/lib/roby/models/plan_object.rb +83 -0
  343. data/lib/roby/models/task.rb +835 -0
  344. data/lib/roby/models/task_event.rb +62 -0
  345. data/lib/roby/models/task_service.rb +78 -0
  346. data/lib/roby/or_generator.rb +88 -0
  347. data/lib/roby/plan.rb +1751 -864
  348. data/lib/roby/plan_object.rb +611 -0
  349. data/lib/roby/plan_service.rb +200 -0
  350. data/lib/roby/promise.rb +332 -0
  351. data/lib/roby/queries.rb +23 -0
  352. data/lib/roby/queries/and_matcher.rb +32 -0
  353. data/lib/roby/queries/any.rb +27 -0
  354. data/lib/roby/queries/code_error_matcher.rb +58 -0
  355. data/lib/roby/queries/event_generator_matcher.rb +9 -0
  356. data/lib/roby/queries/execution_exception_matcher.rb +165 -0
  357. data/lib/roby/queries/index.rb +165 -0
  358. data/lib/roby/queries/localized_error_matcher.rb +149 -0
  359. data/lib/roby/queries/matcher_base.rb +107 -0
  360. data/lib/roby/queries/none.rb +27 -0
  361. data/lib/roby/queries/not_matcher.rb +30 -0
  362. data/lib/roby/queries/op_matcher.rb +8 -0
  363. data/lib/roby/queries/or_matcher.rb +30 -0
  364. data/lib/roby/queries/plan_object_matcher.rb +363 -0
  365. data/lib/roby/queries/query.rb +188 -0
  366. data/lib/roby/queries/task_event_generator_matcher.rb +86 -0
  367. data/lib/roby/queries/task_matcher.rb +344 -0
  368. data/lib/roby/relations.rb +42 -678
  369. data/lib/roby/relations/bidirectional_directed_adjacency_graph.rb +492 -0
  370. data/lib/roby/relations/directed_relation_support.rb +268 -0
  371. data/lib/roby/relations/event_relation_graph.rb +19 -0
  372. data/lib/roby/relations/fork_merge_visitor.rb +154 -0
  373. data/lib/roby/relations/graph.rb +533 -0
  374. data/lib/roby/relations/models/directed_relation_support.rb +11 -0
  375. data/lib/roby/relations/models/graph.rb +75 -0
  376. data/lib/roby/relations/models/task_relation_graph.rb +18 -0
  377. data/lib/roby/relations/space.rb +380 -0
  378. data/lib/roby/relations/task_relation_graph.rb +20 -0
  379. data/lib/roby/robot.rb +85 -38
  380. data/lib/roby/schedulers/basic.rb +155 -25
  381. data/lib/roby/schedulers/null.rb +20 -0
  382. data/lib/roby/schedulers/reporting.rb +31 -0
  383. data/lib/roby/schedulers/state.rb +129 -0
  384. data/lib/roby/schedulers/temporal.rb +91 -0
  385. data/lib/roby/singletons.rb +87 -0
  386. data/lib/roby/standalone.rb +4 -2
  387. data/lib/roby/standard_errors.rb +405 -82
  388. data/lib/roby/state.rb +6 -3
  389. data/lib/roby/state/conf_model.rb +5 -0
  390. data/lib/roby/state/events.rb +181 -95
  391. data/lib/roby/state/goal_model.rb +77 -0
  392. data/lib/roby/state/open_struct.rb +591 -0
  393. data/lib/roby/state/open_struct_model.rb +68 -0
  394. data/lib/roby/state/pos.rb +45 -45
  395. data/lib/roby/state/shapes.rb +11 -11
  396. data/lib/roby/state/state_model.rb +303 -0
  397. data/lib/roby/state/task.rb +43 -0
  398. data/lib/roby/support.rb +88 -148
  399. data/lib/roby/task.rb +1361 -1750
  400. data/lib/roby/task_arguments.rb +428 -0
  401. data/lib/roby/task_event.rb +127 -0
  402. data/lib/roby/task_event_generator.rb +337 -0
  403. data/lib/roby/task_service.rb +6 -0
  404. data/lib/roby/task_structure/conflicts.rb +104 -0
  405. data/lib/roby/task_structure/dependency.rb +932 -0
  406. data/lib/roby/task_structure/error_handling.rb +118 -0
  407. data/lib/roby/task_structure/executed_by.rb +234 -0
  408. data/lib/roby/task_structure/planned_by.rb +90 -0
  409. data/lib/roby/tasks/aggregator.rb +37 -0
  410. data/lib/roby/tasks/external_process.rb +275 -0
  411. data/lib/roby/tasks/group.rb +27 -0
  412. data/lib/roby/tasks/null.rb +19 -0
  413. data/lib/roby/tasks/parallel.rb +43 -0
  414. data/lib/roby/tasks/sequence.rb +88 -0
  415. data/lib/roby/tasks/simple.rb +21 -0
  416. data/lib/roby/{thread_task.rb → tasks/thread.rb} +50 -24
  417. data/lib/roby/tasks/timeout.rb +17 -0
  418. data/lib/roby/tasks/virtual.rb +55 -0
  419. data/lib/roby/template_plan.rb +7 -0
  420. data/lib/roby/test/aruba_minitest.rb +74 -0
  421. data/lib/roby/test/assertion.rb +16 -0
  422. data/lib/roby/test/assertions.rb +490 -0
  423. data/lib/roby/test/common.rb +368 -591
  424. data/lib/roby/test/dsl.rb +149 -0
  425. data/lib/roby/test/error.rb +18 -0
  426. data/lib/roby/test/event_reporter.rb +83 -0
  427. data/lib/roby/test/execution_expectations.rb +1134 -0
  428. data/lib/roby/test/expect_execution.rb +151 -0
  429. data/lib/roby/test/minitest_helpers.rb +166 -0
  430. data/lib/roby/test/roby_app_helpers.rb +200 -0
  431. data/lib/roby/test/run_planners.rb +155 -0
  432. data/lib/roby/test/self.rb +112 -0
  433. data/lib/roby/test/spec.rb +198 -0
  434. data/lib/roby/test/tasks/empty_task.rb +4 -4
  435. data/lib/roby/test/tasks/goto.rb +28 -27
  436. data/lib/roby/test/teardown_plans.rb +100 -0
  437. data/lib/roby/test/testcase.rb +239 -307
  438. data/lib/roby/test/tools.rb +159 -155
  439. data/lib/roby/test/validate_state_machine.rb +75 -0
  440. data/lib/roby/transaction.rb +1125 -0
  441. data/lib/roby/transaction/event_generator_proxy.rb +63 -0
  442. data/lib/roby/transaction/plan_object_proxy.rb +99 -0
  443. data/lib/roby/transaction/plan_service_proxy.rb +43 -0
  444. data/lib/roby/transaction/proxying.rb +120 -0
  445. data/lib/roby/transaction/task_event_generator_proxy.rb +19 -0
  446. data/lib/roby/transaction/task_proxy.rb +135 -0
  447. data/lib/roby/until_generator.rb +30 -0
  448. data/lib/roby/version.rb +5 -0
  449. data/lib/roby/yard.rb +169 -0
  450. data/lib/yard-roby.rb +1 -0
  451. data/manifest.xml +32 -6
  452. data/roby.gemspec +59 -0
  453. metadata +788 -587
  454. data/Manifest.txt +0 -321
  455. data/NOTES +0 -4
  456. data/README.txt +0 -166
  457. data/TODO.txt +0 -146
  458. data/app/README.txt +0 -24
  459. data/app/Rakefile +0 -8
  460. data/app/config/ROBOT.rb +0 -5
  461. data/app/config/init.rb +0 -33
  462. data/app/config/roby.yml +0 -3
  463. data/app/controllers/ROBOT.rb +0 -2
  464. data/app/planners/ROBOT/main.rb +0 -6
  465. data/app/planners/main.rb +0 -5
  466. data/app/scripts/distributed +0 -3
  467. data/app/scripts/generate/bookmarks +0 -3
  468. data/app/scripts/replay +0 -3
  469. data/app/scripts/results +0 -3
  470. data/app/scripts/run +0 -3
  471. data/app/scripts/server +0 -3
  472. data/app/scripts/shell +0 -3
  473. data/app/scripts/test +0 -3
  474. data/app/tasks/.gitattributes +0 -0
  475. data/app/tasks/ROBOT/.gitattributes +0 -0
  476. data/bin/roby-shell +0 -25
  477. data/doc/guide/src/basics/app.page +0 -139
  478. data/doc/guide/src/basics/index.page +0 -11
  479. data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
  480. data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
  481. data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
  482. data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
  483. data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
  484. data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
  485. data/doc/guide/src/basics/relations_display.page +0 -203
  486. data/doc/guide/src/basics/shell.page +0 -102
  487. data/doc/guide/src/default.css +0 -319
  488. data/doc/guide/src/introduction/index.page +0 -29
  489. data/doc/guide/src/introduction/publications.page +0 -14
  490. data/doc/guide/src/relations/dependency.page +0 -89
  491. data/doc/guide/src/relations/index.page +0 -12
  492. data/ext/droby/dump.cc +0 -175
  493. data/ext/droby/extconf.rb +0 -3
  494. data/ext/graph/algorithm.cc +0 -746
  495. data/ext/graph/extconf.rb +0 -7
  496. data/ext/graph/graph.cc +0 -575
  497. data/ext/graph/graph.hh +0 -183
  498. data/ext/graph/iterator_sequence.hh +0 -102
  499. data/ext/graph/undirected_dfs.hh +0 -226
  500. data/ext/graph/undirected_graph.hh +0 -421
  501. data/lib/roby/app/scripts/generate/bookmarks.rb +0 -162
  502. data/lib/roby/app/scripts/replay.rb +0 -31
  503. data/lib/roby/app/scripts/server.rb +0 -18
  504. data/lib/roby/basic_object.rb +0 -151
  505. data/lib/roby/config.rb +0 -14
  506. data/lib/roby/distributed.rb +0 -36
  507. data/lib/roby/distributed/base.rb +0 -448
  508. data/lib/roby/distributed/communication.rb +0 -875
  509. data/lib/roby/distributed/connection_space.rb +0 -616
  510. data/lib/roby/distributed/distributed_object.rb +0 -206
  511. data/lib/roby/distributed/drb.rb +0 -62
  512. data/lib/roby/distributed/notifications.rb +0 -531
  513. data/lib/roby/distributed/peer.rb +0 -555
  514. data/lib/roby/distributed/protocol.rb +0 -529
  515. data/lib/roby/distributed/proxy.rb +0 -343
  516. data/lib/roby/distributed/subscription.rb +0 -311
  517. data/lib/roby/distributed/transaction.rb +0 -498
  518. data/lib/roby/external_process_task.rb +0 -225
  519. data/lib/roby/graph.rb +0 -160
  520. data/lib/roby/log.rb +0 -3
  521. data/lib/roby/log/chronicle.rb +0 -303
  522. data/lib/roby/log/console.rb +0 -74
  523. data/lib/roby/log/data_stream.rb +0 -275
  524. data/lib/roby/log/dot.rb +0 -279
  525. data/lib/roby/log/event_stream.rb +0 -161
  526. data/lib/roby/log/file.rb +0 -396
  527. data/lib/roby/log/gui/basic_display.ui +0 -83
  528. data/lib/roby/log/gui/basic_display_ui.rb +0 -89
  529. data/lib/roby/log/gui/chronicle.rb +0 -26
  530. data/lib/roby/log/gui/chronicle_view.rb +0 -40
  531. data/lib/roby/log/gui/chronicle_view.ui +0 -70
  532. data/lib/roby/log/gui/chronicle_view_ui.rb +0 -90
  533. data/lib/roby/log/gui/data_displays.rb +0 -171
  534. data/lib/roby/log/gui/data_displays.ui +0 -155
  535. data/lib/roby/log/gui/data_displays_ui.rb +0 -146
  536. data/lib/roby/log/gui/notifications.rb +0 -26
  537. data/lib/roby/log/gui/relations.rb +0 -269
  538. data/lib/roby/log/gui/relations.ui +0 -123
  539. data/lib/roby/log/gui/relations_ui.rb +0 -120
  540. data/lib/roby/log/gui/relations_view.rb +0 -185
  541. data/lib/roby/log/gui/relations_view.ui +0 -149
  542. data/lib/roby/log/gui/relations_view_ui.rb +0 -144
  543. data/lib/roby/log/gui/replay.rb +0 -366
  544. data/lib/roby/log/gui/replay_controls.rb +0 -206
  545. data/lib/roby/log/gui/replay_controls.ui +0 -282
  546. data/lib/roby/log/gui/replay_controls_ui.rb +0 -249
  547. data/lib/roby/log/gui/runtime.rb +0 -130
  548. data/lib/roby/log/hooks.rb +0 -186
  549. data/lib/roby/log/logger.rb +0 -203
  550. data/lib/roby/log/notifications.rb +0 -244
  551. data/lib/roby/log/plan_rebuilder.rb +0 -468
  552. data/lib/roby/log/relations.rb +0 -1084
  553. data/lib/roby/log/server.rb +0 -547
  554. data/lib/roby/log/sqlite.rb +0 -47
  555. data/lib/roby/log/timings.rb +0 -233
  556. data/lib/roby/plan-object.rb +0 -371
  557. data/lib/roby/planning.rb +0 -13
  558. data/lib/roby/planning/loops.rb +0 -309
  559. data/lib/roby/planning/model.rb +0 -1012
  560. data/lib/roby/planning/task.rb +0 -180
  561. data/lib/roby/query.rb +0 -655
  562. data/lib/roby/relations/conflicts.rb +0 -67
  563. data/lib/roby/relations/dependency.rb +0 -358
  564. data/lib/roby/relations/ensured.rb +0 -19
  565. data/lib/roby/relations/error_handling.rb +0 -22
  566. data/lib/roby/relations/events.rb +0 -7
  567. data/lib/roby/relations/executed_by.rb +0 -208
  568. data/lib/roby/relations/influence.rb +0 -10
  569. data/lib/roby/relations/planned_by.rb +0 -63
  570. data/lib/roby/state/information.rb +0 -55
  571. data/lib/roby/state/state.rb +0 -367
  572. data/lib/roby/task-operations.rb +0 -186
  573. data/lib/roby/task_index.rb +0 -80
  574. data/lib/roby/test/distributed.rb +0 -230
  575. data/lib/roby/test/tasks/simple_task.rb +0 -23
  576. data/lib/roby/transactions.rb +0 -507
  577. data/lib/roby/transactions/proxy.rb +0 -325
  578. data/plugins/fault_injection/History.txt +0 -4
  579. data/plugins/fault_injection/README.txt +0 -34
  580. data/plugins/fault_injection/Rakefile +0 -12
  581. data/plugins/fault_injection/TODO.txt +0 -0
  582. data/plugins/fault_injection/app.rb +0 -52
  583. data/plugins/fault_injection/fault_injection.rb +0 -89
  584. data/plugins/fault_injection/test/test_fault_injection.rb +0 -78
  585. data/plugins/subsystems/README.txt +0 -37
  586. data/plugins/subsystems/Rakefile +0 -13
  587. data/plugins/subsystems/app.rb +0 -182
  588. data/plugins/subsystems/test/app/README +0 -24
  589. data/plugins/subsystems/test/app/Rakefile +0 -8
  590. data/plugins/subsystems/test/app/config/app.yml +0 -71
  591. data/plugins/subsystems/test/app/config/init.rb +0 -12
  592. data/plugins/subsystems/test/app/config/roby.yml +0 -3
  593. data/plugins/subsystems/test/app/planners/main.rb +0 -20
  594. data/plugins/subsystems/test/app/scripts/distributed +0 -3
  595. data/plugins/subsystems/test/app/scripts/replay +0 -3
  596. data/plugins/subsystems/test/app/scripts/results +0 -3
  597. data/plugins/subsystems/test/app/scripts/run +0 -3
  598. data/plugins/subsystems/test/app/scripts/server +0 -3
  599. data/plugins/subsystems/test/app/scripts/shell +0 -3
  600. data/plugins/subsystems/test/app/scripts/test +0 -3
  601. data/plugins/subsystems/test/app/tasks/services.rb +0 -15
  602. data/plugins/subsystems/test/test_subsystems.rb +0 -78
  603. data/test/distributed/test_communication.rb +0 -195
  604. data/test/distributed/test_connection.rb +0 -284
  605. data/test/distributed/test_execution.rb +0 -378
  606. data/test/distributed/test_mixed_plan.rb +0 -341
  607. data/test/distributed/test_plan_notifications.rb +0 -238
  608. data/test/distributed/test_protocol.rb +0 -525
  609. data/test/distributed/test_query.rb +0 -106
  610. data/test/distributed/test_remote_plan.rb +0 -491
  611. data/test/distributed/test_transaction.rb +0 -466
  612. data/test/mockups/external_process +0 -28
  613. data/test/mockups/tasks.rb +0 -27
  614. data/test/planning/test_loops.rb +0 -432
  615. data/test/planning/test_model.rb +0 -427
  616. data/test/planning/test_task.rb +0 -126
  617. data/test/relations/test_conflicts.rb +0 -42
  618. data/test/relations/test_dependency.rb +0 -324
  619. data/test/relations/test_ensured.rb +0 -38
  620. data/test/relations/test_executed_by.rb +0 -224
  621. data/test/relations/test_planned_by.rb +0 -56
  622. data/test/suite_core.rb +0 -29
  623. data/test/suite_distributed.rb +0 -10
  624. data/test/suite_planning.rb +0 -4
  625. data/test/suite_relations.rb +0 -8
  626. data/test/tasks/test_external_process.rb +0 -126
  627. data/test/tasks/test_thread_task.rb +0 -70
  628. data/test/test_bgl.rb +0 -528
  629. data/test/test_event.rb +0 -969
  630. data/test/test_exceptions.rb +0 -591
  631. data/test/test_execution_engine.rb +0 -987
  632. data/test/test_gui.rb +0 -20
  633. data/test/test_interface.rb +0 -43
  634. data/test/test_log.rb +0 -125
  635. data/test/test_log_server.rb +0 -133
  636. data/test/test_plan.rb +0 -418
  637. data/test/test_query.rb +0 -424
  638. data/test/test_relations.rb +0 -260
  639. data/test/test_state.rb +0 -432
  640. data/test/test_support.rb +0 -16
  641. data/test/test_task.rb +0 -1181
  642. data/test/test_testcase.rb +0 -138
  643. data/test/test_transactions.rb +0 -610
  644. data/test/test_transactions_proxy.rb +0 -216
@@ -1,987 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path(File.join('..', 'lib'), File.dirname(__FILE__))
2
- require 'roby/test/common'
3
- require 'flexmock'
4
- require 'roby/test/tasks/simple_task'
5
- require 'roby/test/tasks/empty_task'
6
- require 'mockups/tasks'
7
- require 'flexmock'
8
- require 'utilrb/hash/slice'
9
- require 'roby/log'
10
-
11
- class TC_ExecutionEngine < Test::Unit::TestCase
12
- include Roby::Test
13
-
14
- def setup
15
- super
16
- Roby::Log.add_logger(@finalized_tasks_recorder = FinalizedTaskRecorder.new)
17
- end
18
- def teardown
19
- Roby::Log.remove_logger @finalized_tasks_recorder
20
- super
21
- end
22
-
23
- def test_gather_propagation
24
- e1, e2, e3 = EventGenerator.new(true), EventGenerator.new(true), EventGenerator.new(true)
25
- plan.add [e1, e2, e3]
26
-
27
- set = engine.gather_propagation do
28
- e1.call(1)
29
- e1.call(4)
30
- e2.emit(2)
31
- e2.emit(3)
32
- e3.call(5)
33
- e3.emit(6)
34
- end
35
- assert_equal({ e1 => [nil, [nil, [1], nil, nil, [4], nil]], e2 => [[nil, [2], nil, nil, [3], nil], nil], e3 => [[nil, [6], nil], [nil, [5], nil]] }, set)
36
- end
37
-
38
- def test_emission_is_forbidden_outside_propagation_phase
39
- # Temporarily disable logging as we are going to generate a fatal error
40
- # ..
41
- Roby.logger.level = Logger::FATAL
42
-
43
- plan.add_permanent(task = SimpleTask.new)
44
-
45
- error = nil
46
- failure = lambda do
47
- begin
48
- task.emit(:start)
49
- rescue Exception => e
50
- error = e
51
- raise
52
- end
53
- nil
54
- end
55
- plan.structure_checks << failure
56
-
57
- engine.run
58
- engine.join
59
- assert_kind_of(PhaseMismatch, error)
60
-
61
- ensure
62
- plan.structure_checks.delete_if { |v| v == failure }
63
- end
64
-
65
- def test_propagation_handlers
66
- test_obj = Object.new
67
- def test_obj.mock_handler(plan)
68
- @mockup.called(plan)
69
- end
70
-
71
- FlexMock.use do |mock|
72
- test_obj.instance_variable_set :@mockup, mock
73
- id = engine.add_propagation_handler test_obj.method(:mock_handler)
74
-
75
- mock.should_receive(:called).with(plan).twice
76
- process_events
77
- process_events
78
- engine.remove_propagation_handler id
79
- process_events
80
- end
81
-
82
- FlexMock.use do |mock|
83
- test_obj.instance_variable_set :@mockup, mock
84
- id = engine.add_propagation_handler { |plan| mock.called(plan) }
85
-
86
- mock.should_receive(:called).with(plan).twice
87
- process_events
88
- process_events
89
- engine.remove_propagation_handler id
90
- process_events
91
- end
92
-
93
- assert_raises(ArgumentError) do
94
- engine.add_propagation_handler { |plan, failure| mock.called(plan) }
95
- end
96
-
97
- assert_nothing_raised { process_events }
98
- end
99
-
100
- def test_prepare_propagation
101
- g1, g2 = EventGenerator.new(true), EventGenerator.new(true)
102
- ev = Event.new(g2, 0, nil)
103
-
104
- step = [nil, [1], nil, nil, [4], nil]
105
- source_events, source_generators, context = engine.prepare_propagation(nil, false, step)
106
- assert_equal(ValueSet.new, source_events)
107
- assert_equal(ValueSet.new, source_generators)
108
- assert_equal([1, 4], context)
109
-
110
- step = [nil, [], nil, nil, [4], nil]
111
- source_events, source_generators, context = engine.prepare_propagation(nil, false, step)
112
- assert_equal(ValueSet.new, source_events)
113
- assert_equal(ValueSet.new, source_generators)
114
- assert_equal([4], context)
115
-
116
- step = [g1, [], nil, ev, [], nil]
117
- source_events, source_generators, context = engine.prepare_propagation(nil, false, step)
118
- assert_equal([g1, g2].to_value_set, source_generators)
119
- assert_equal([ev].to_value_set, source_events)
120
- assert_equal(nil, context)
121
-
122
- step = [g2, [], nil, ev, [], nil]
123
- source_events, source_generators, context = engine.prepare_propagation(nil, false, step)
124
- assert_equal([g2].to_value_set, source_generators)
125
- assert_equal([ev].to_value_set, source_events)
126
- assert_equal(nil, context)
127
- end
128
-
129
- def test_precedence_graph
130
- e1, e2 = EventGenerator.new(true), EventGenerator.new(true)
131
- engine.event_ordering << :bla
132
- plan.add e1
133
- assert(engine.event_ordering.empty?)
134
- plan.add e2
135
-
136
- engine.event_ordering << :bla
137
- task = Roby::Task.new
138
- plan.add(task)
139
- assert(engine.event_ordering.empty?)
140
- assert(EventStructure::Precedence.linked?(task.event(:start), task.event(:updated_data)))
141
-
142
- engine.event_ordering << :bla
143
- e1.signals e2
144
- assert(EventStructure::Precedence.linked?(e1, e2))
145
- assert(engine.event_ordering.empty?)
146
-
147
- engine.event_ordering << :bla
148
- e1.remove_signal e2
149
- assert(engine.event_ordering.empty?)
150
- assert(!EventStructure::Precedence.linked?(e1, e2))
151
- end
152
-
153
- def test_next_step
154
- # For the test to be valid, we need +pending+ to have a deterministic ordering
155
- # Fix that here
156
- e1, e2 = EventGenerator.new(true), EventGenerator.new(true)
157
- plan.add [e1, e2]
158
- pending = [ [e1, [true, nil, nil, nil]], [e2, [false, nil, nil, nil]] ]
159
- def pending.each_key; each { |(k, v)| yield(k) } end
160
- def pending.delete(ev); delete_if { |(k, v)| k == ev } end
161
-
162
- e1.add_precedence e2
163
- assert_equal(e1, engine.next_event(pending).first)
164
-
165
- e1.remove_precedence e2
166
- e2.add_precedence e1
167
- assert_equal(e2, engine.next_event(pending).first)
168
- end
169
-
170
- def test_delay
171
- FlexMock.use(Time) do |time_proxy|
172
- current_time = Time.now + 5
173
- time_proxy.should_receive(:now).and_return { current_time }
174
-
175
- plan.add_mission(t = SimpleTask.new)
176
- e = EventGenerator.new(true)
177
- t.event(:start).signals e, :delay => 0.1
178
- engine.once { t.start! }
179
- process_events
180
- assert(!e.happened?)
181
- current_time += 0.1
182
- process_events
183
- assert(e.happened?)
184
- end
185
- end
186
-
187
- def test_duplicate_signals
188
- plan.add_mission(t = SimpleTask.new)
189
-
190
- FlexMock.use do |mock|
191
- t.on(:start) { |event| t.emit(:success, *event.context) }
192
- t.on(:start) { |event| t.emit(:success, *event.context) }
193
-
194
- t.on(:success) { |event| mock.success(event.context) }
195
- t.on(:stop) { |event| mock.stop(event.context) }
196
- mock.should_receive(:success).with([42, 42]).once.ordered
197
- mock.should_receive(:stop).with([42, 42]).once.ordered
198
- t.start!(42)
199
- end
200
- end
201
- def test_diamond_structure
202
- a = Class.new(SimpleTask) do
203
- event :child_success
204
- event :child_stop
205
- forward :child_success => :child_stop
206
- end.new(:id => 'a')
207
-
208
- plan.add_mission(a)
209
- a.depends_on(b = SimpleTask.new(:id => 'b'))
210
-
211
- b.forward_to(:success, a, :child_success)
212
- b.forward_to(:stop, a, :child_stop)
213
-
214
- FlexMock.use do |mock|
215
- a.on(:child_stop) { mock.stopped }
216
- mock.should_receive(:stopped).once.ordered
217
- a.start!
218
- b.start!
219
- b.success!
220
- end
221
- end
222
-
223
- def test_signal_forward
224
- forward = EventGenerator.new(true)
225
- signal = EventGenerator.new(true)
226
- plan.add [forward, signal]
227
-
228
- FlexMock.use do |mock|
229
- sink = EventGenerator.new do |context|
230
- mock.command_called(context)
231
- sink.emit(42)
232
- end
233
- sink.on { |event| mock.handler_called(event.context) }
234
-
235
- forward.forward_to sink
236
- signal.signals sink
237
-
238
- seed = lambda do
239
- forward.call(24)
240
- signal.call(42)
241
- end
242
- mock.should_receive(:command_called).with([42]).once.ordered
243
- mock.should_receive(:handler_called).with([42, 24]).once.ordered
244
- engine.propagate_events([seed])
245
- end
246
- end
247
-
248
- module LogEventGathering
249
- class << self
250
- attr_accessor :mockup
251
- def handle(name, obj)
252
- mockup.send(name, obj, obj.engine.propagation_sources) if mockup
253
- end
254
- end
255
-
256
- def signalling(event, to)
257
- super if defined? super
258
- LogEventGathering.handle(:signalling, self)
259
- end
260
- def forwarding(event, to)
261
- super if defined? super
262
- LogEventGathering.handle(:forwarding, self)
263
- end
264
- def emitting(context)
265
- super if defined? super
266
- LogEventGathering.handle(:emitting, self)
267
- end
268
- def calling(context)
269
- super if defined? super
270
- LogEventGathering.handle(:calling, self)
271
- end
272
- end
273
- EventGenerator.include LogEventGathering
274
-
275
- def test_log_events
276
- FlexMock.use do |mock|
277
- LogEventGathering.mockup = mock
278
- dst = EventGenerator.new { }
279
- src = EventGenerator.new { dst.call }
280
- plan.add [src, dst]
281
-
282
- mock.should_receive(:signalling).never
283
- mock.should_receive(:forwarding).never
284
- mock.should_receive(:calling).with(src, [].to_value_set).once
285
- mock.should_receive(:calling).with(dst, [src].to_value_set).once
286
- src.call
287
- end
288
-
289
- ensure
290
- LogEventGathering.mockup = nil
291
- end
292
-
293
- def test_add_framework_errors
294
- # Shut up the logger in this test
295
- Roby.logger.level = Logger::FATAL
296
- exception = begin; raise RuntimeError
297
- rescue; $!
298
- end
299
-
300
- Roby.app.abort_on_application_exception = false
301
- assert_nothing_raised { engine.add_framework_error(exception, :exceptions) }
302
-
303
- Roby.app.abort_on_application_exception = true
304
- assert_raises(RuntimeError) { engine.add_framework_error(exception, :exceptions) }
305
- end
306
-
307
- def test_event_loop
308
- plan.add_mission(start_node = EmptyTask.new)
309
- next_event = [ start_node, :start ]
310
- plan.add_mission(if_node = ChoiceTask.new)
311
- start_node.on(:stop) { next_event = [if_node, :start] }
312
- if_node.on(:stop) { }
313
-
314
- engine.propagation_handlers << lambda do |plan|
315
- next unless next_event
316
- task, event = *next_event
317
- next_event = nil
318
- task.event(event).call(nil)
319
- end
320
- process_events
321
- assert(start_node.finished?)
322
-
323
- process_events
324
- assert(if_node.finished?)
325
- end
326
-
327
- def test_every
328
- # Check that every(cycle_length) works fine
329
- engine.run
330
-
331
- samples = []
332
- id = engine.every(0.1) do
333
- samples << engine.cycle_start
334
- end
335
- sleep(1)
336
- engine.remove_periodic_handler(id)
337
- size = samples.size
338
- assert(size > 2, samples.map { |t| t.to_hms })
339
-
340
- samples.each_cons(2) do |a, b|
341
- assert_in_delta(0.1, b - a, 0.001)
342
- end
343
-
344
- # Check that no samples have been added after the 'remove_periodic_handler'
345
- assert_equal(size, samples.size)
346
- end
347
-
348
- def test_once
349
- FlexMock.use do |mock|
350
- engine.once { mock.called }
351
- mock.should_receive(:called).once
352
- process_events
353
- end
354
- FlexMock.use do |mock|
355
- engine.once { mock.called }
356
- mock.should_receive(:called).once
357
- process_events
358
- process_events
359
- end
360
- end
361
-
362
- def test_failing_once
363
- Roby.logger.level = Logger::FATAL
364
- Roby.app.abort_on_exception = true
365
- engine.run
366
-
367
- FlexMock.use do |mock|
368
- engine.once { mock.called; raise }
369
- mock.should_receive(:called).once
370
-
371
- assert_raises(ExecutionQuitError) do
372
- engine.wait_one_cycle
373
- engine.join
374
- end
375
- end
376
- end
377
-
378
- class SpecificException < RuntimeError; end
379
- def test_unhandled_event_exceptions
380
- Roby.app.abort_on_exception = true
381
-
382
- # Test that the event is not pending if the command raises
383
- model = Class.new(SimpleTask) do
384
- event :start do |context|
385
- raise SpecificException, "bla"
386
- end
387
- end
388
- plan.add_permanent(t = model.new)
389
-
390
- assert_original_error(SpecificException, CommandFailed) { t.start! }
391
- assert(!t.event(:start).pending?)
392
-
393
- # Check that the propagation is pruned if the command raises
394
- t = nil
395
- FlexMock.use do |mock|
396
- t = Class.new(SimpleTask) do
397
- event :start do |context|
398
- mock.command_called
399
- raise SpecificException, "bla"
400
- emit :start
401
- end
402
- on(:start) { |ev| mock.handler_called }
403
- end.new
404
- plan.add_permanent(t)
405
-
406
- mock.should_receive(:command_called).once
407
- mock.should_receive(:handler_called).never
408
-
409
- engine.once { t.start!(nil) }
410
- assert_original_error(SpecificException, CommandFailed) { process_events }
411
- assert(!t.event(:start).pending)
412
- end
413
-
414
- # Check that the task has been garbage collected in the process
415
- assert(! plan.include?(t))
416
- end
417
-
418
- def apply_check_structure(&block)
419
- Plan.structure_checks.clear
420
- Plan.structure_checks << lambda(&block)
421
- process_events
422
- ensure
423
- Plan.structure_checks.clear
424
- end
425
-
426
- def test_check_structure
427
- Roby.logger.level = Logger::FATAL
428
- Roby.app.abort_on_exception = false
429
-
430
- # Check on a single task
431
- plan.add_mission(t = SimpleTask.new)
432
- apply_check_structure { LocalizedError.new(t) }
433
- assert(! plan.include?(t))
434
-
435
- # Make sure that a task which has been repaired will not be killed
436
- plan.add_mission(t = SimpleTask.new)
437
- did_once = false
438
- apply_check_structure do
439
- unless did_once
440
- did_once = true
441
- LocalizedError.new(t)
442
- end
443
- end
444
- assert(plan.include?(t))
445
-
446
- # Check that whole task trees are killed
447
- t0, t1, t2, t3 = prepare_plan :discover => 4
448
- t0.depends_on t2
449
- t1.depends_on t2
450
- t2.depends_on t3
451
-
452
- plan.add_mission(t0)
453
- plan.add_mission(t1)
454
- FlexMock.use do |mock|
455
- mock.should_receive(:checking).twice
456
- apply_check_structure do
457
- mock.checking
458
- LocalizedError.new(t2)
459
- end
460
- end
461
- assert(!plan.include?(t0))
462
- assert(!plan.include?(t1))
463
- assert(!plan.include?(t2))
464
- process_events
465
- assert(!plan.include?(t3))
466
-
467
- # Check that we can kill selectively by returning a hash
468
- t0, t1, t2 = prepare_plan :discover => 3
469
- t0.depends_on t2
470
- t1.depends_on t2
471
- plan.add_mission(t0)
472
- plan.add_mission(t1)
473
- apply_check_structure { { LocalizedError.new(t2) => t0 } }
474
- assert(!plan.include?(t0))
475
- assert(plan.include?(t1))
476
- assert(plan.include?(t2))
477
- end
478
-
479
- def test_at_cycle_end
480
- # Shut up the logger in this test
481
- Roby.logger.level = Logger::FATAL
482
- Roby.app.abort_on_application_exception = false
483
-
484
- FlexMock.use do |mock|
485
- mock.should_receive(:before_error).at_least.once
486
- mock.should_receive(:after_error).never
487
- mock.should_receive(:called).at_least.once
488
-
489
- engine.at_cycle_end do
490
- mock.before_error
491
- raise
492
- mock.after_error
493
- end
494
-
495
- engine.at_cycle_end do
496
- mock.called
497
- unless engine.quitting?
498
- engine.quit
499
- end
500
- end
501
- engine.run
502
- engine.join
503
- end
504
- end
505
-
506
- def test_inside_outside_control
507
- # First, no control thread
508
- assert(engine.inside_control?)
509
- assert(engine.outside_control?)
510
-
511
- # Add a fake control thread
512
- begin
513
- engine.thread = Thread.main
514
- assert(engine.inside_control?)
515
- assert(!engine.outside_control?)
516
-
517
- t = Thread.new do
518
- assert(!engine.inside_control?)
519
- assert(engine.outside_control?)
520
- end
521
- t.value
522
- ensure
523
- engine.thread = nil
524
- end
525
-
526
- # .. and test with the real one
527
- engine.run
528
- engine.execute do
529
- assert(engine.inside_control?)
530
- assert(!engine.outside_control?)
531
- end
532
- assert(!engine.inside_control?)
533
- assert(engine.outside_control?)
534
- end
535
-
536
- def test_execute
537
- # Set a fake control thread
538
- engine.thread = Thread.main
539
-
540
- FlexMock.use do |mock|
541
- mock.should_receive(:thread_before).once.ordered
542
- mock.should_receive(:main_before).once.ordered
543
- mock.should_receive(:execute).once.ordered.with(Thread.current).and_return(42)
544
- mock.should_receive(:main_after).once.ordered(:finish)
545
- mock.should_receive(:thread_after).once.ordered(:finish)
546
-
547
- returned_value = nil
548
- t = Thread.new do
549
- mock.thread_before
550
- returned_value = engine.execute do
551
- mock.execute(Thread.current)
552
- end
553
- mock.thread_after
554
- end
555
-
556
- # Wait for the thread to block
557
- while !t.stop?; sleep(0.1) end
558
- mock.main_before
559
- assert(t.alive?)
560
- process_events
561
- mock.main_after
562
- t.join
563
-
564
- assert_equal(42, returned_value)
565
- end
566
-
567
- ensure
568
- engine.thread = nil
569
- end
570
-
571
- def test_execute_error
572
- assert(!engine.thread)
573
- # Set a fake control thread
574
- engine.thread = Thread.main
575
- assert(!engine.quitting?)
576
-
577
- returned_value = nil
578
- t = Thread.new do
579
- returned_value = begin
580
- engine.execute do
581
- raise ArgumentError
582
- end
583
- rescue ArgumentError => e
584
- e
585
- end
586
- end
587
-
588
- # Wait for the thread to block
589
- while !t.stop?; sleep(0.1) end
590
- process_events
591
- t.join
592
-
593
- assert_kind_of(ArgumentError, returned_value)
594
- assert(!engine.quitting?)
595
-
596
- ensure
597
- engine.thread = nil
598
- end
599
-
600
- def test_wait_until
601
- # Set a fake control thread
602
- engine.thread = Thread.main
603
-
604
- plan.add_permanent(task = SimpleTask.new)
605
- t = Thread.new do
606
- engine.wait_until(task.event(:start)) do
607
- task.start!
608
- end
609
- end
610
-
611
- while !t.stop?; sleep(0.1) end
612
- process_events
613
- assert_nothing_raised { t.value }
614
-
615
- ensure
616
- engine.thread = nil
617
- end
618
-
619
- def test_wait_until_unreachable
620
- # Set a fake control thread
621
- engine.thread = Thread.main
622
-
623
- plan.add_permanent(task = SimpleTask.new)
624
- t = Thread.new do
625
- begin
626
- engine.wait_until(task.event(:success)) do
627
- task.start!
628
- task.stop!
629
- end
630
- rescue Exception => e
631
- e
632
- end
633
- end
634
-
635
- while !t.stop?; sleep(0.1) end
636
- process_events
637
-
638
- result = t.value
639
- assert_kind_of(UnreachableEvent, result)
640
- assert_equal(task.event(:success), result.failed_generator)
641
-
642
- ensure
643
- engine.thread = nil
644
- end
645
-
646
- class CaptureLastStats
647
- attr_reader :last_stats
648
- def splat?; true end
649
- def logs_message?(m); m == :cycle_end end
650
- def close; end
651
- def cycle_end(time, stats)
652
- @last_stats = stats
653
- end
654
- end
655
-
656
- def test_stats
657
- require 'roby/log'
658
- engine.run
659
-
660
- capture = CaptureLastStats.new
661
- Roby::Log.add_logger capture
662
-
663
- time_events = [:real_start, :events, :structure_check, :exception_propagation, :exception_fatal, :garbage_collect, :application_errors, :ruby_gc, :sleep, :end]
664
- 10.times do
665
- engine.wait_one_cycle
666
- next unless capture.last_stats
667
-
668
- Roby.synchronize do
669
- timepoints = capture.last_stats.slice(*time_events)
670
- assert(timepoints.all? { |name, d| d > 0 })
671
-
672
- sorted_by_time = timepoints.sort_by { |name, d| d }
673
- sorted_by_name = timepoints.sort_by { |name, d| time_events.index(name) }
674
- sorted_by_time.each_with_index do |(name, d), i|
675
- assert(sorted_by_name[i][1] == d)
676
- end
677
- end
678
- end
679
-
680
- ensure
681
- Roby::Log.remove_logger capture if capture
682
- end
683
-
684
- def clear_finalized
685
- Roby::Log.flush
686
- @finalized_tasks_recorder.clear
687
- end
688
- # Returns the RemoteID for tasks that have been finalized since the last
689
- # call to #clear_finalized.
690
- def finalized_tasks; @finalized_tasks_recorder.tasks end
691
- # Returns the RemoteID for events that have been finalized since the last
692
- # call to #clear_finalized.
693
- def finalized_events; @finalized_tasks_recorder.events end
694
- class FinalizedTaskRecorder
695
- attribute(:tasks) { Array.new }
696
- attribute(:events) { Array.new }
697
- def logs_message?(m); m == :finalized_task || m == :finalized_event end
698
- def finalized_task(time, plan, task)
699
- tasks << task
700
- end
701
- def finalized_event(time, plan, event)
702
- events << event unless event.respond_to?(:task)
703
- end
704
- def clear
705
- tasks.clear
706
- events.clear
707
- end
708
- def close; end
709
- def splat?; true end
710
- end
711
-
712
- def assert_finalizes(plan, unneeded, finalized = nil)
713
- finalized ||= unneeded
714
- finalized = finalized.map { |obj| obj.remote_id }
715
- clear_finalized
716
-
717
- yield if block_given?
718
-
719
- assert_equal(unneeded.to_set, plan.unneeded_tasks.to_set)
720
- engine.garbage_collect
721
- process_events
722
- engine.garbage_collect
723
-
724
- # !!! We are actually relying on the logging queue for this to work.
725
- # make sure it is empty before testing anything
726
- Roby::Log.flush
727
-
728
- assert_equal(finalized.to_set, (finalized_tasks.to_set | finalized_events.to_set) )
729
- assert(! finalized.any? { |t| plan.include?(t) })
730
- end
731
-
732
- def test_garbage_collect_tasks
733
- klass = Class.new(Task) do
734
- attr_accessor :delays
735
-
736
- event(:start, :command => true)
737
- event(:stop) do |context|
738
- if delays
739
- return
740
- else
741
- emit(:stop)
742
- end
743
- end
744
- end
745
-
746
- t1, t2, t3, t4, t5, t6, t7, t8, p1 = (1..9).map { |i| klass.new(:id => i) }
747
- t1.depends_on t3
748
- t2.depends_on t3
749
- t3.depends_on t4
750
- t5.depends_on t4
751
- t5.planned_by p1
752
- p1.depends_on t6
753
-
754
- t7.depends_on t8
755
-
756
- [t1, t2, t5].each { |t| plan.add_mission(t) }
757
- plan.add_permanent(t7)
758
-
759
- assert_finalizes(plan, [])
760
- assert_finalizes(plan, [t1]) { plan.unmark_mission(t1) }
761
- assert_finalizes(plan, [t2, t3]) do
762
- t2.start!(nil)
763
- plan.unmark_mission(t2)
764
- end
765
- assert_finalizes(plan, [t5, t4, p1, t6], []) do
766
- t5.delays = true
767
- t5.start!(nil)
768
- plan.unmark_mission(t5)
769
- end
770
- assert(t5.event(:stop).pending?)
771
- assert_finalizes(plan, [t5, t4, p1, t6]) do
772
- t5.event(:stop).emit(nil)
773
- end
774
- end
775
-
776
- def test_force_garbage_collect_tasks
777
- t1 = Class.new(Task) do
778
- event(:stop) { |context| }
779
- end.new
780
- t2 = Task.new
781
- t1.depends_on t2
782
-
783
- plan.add_mission(t1)
784
- t1.start!
785
- assert_finalizes(plan, []) do
786
- engine.garbage_collect([t1])
787
- end
788
- assert(t1.event(:stop).pending?)
789
-
790
- assert_finalizes(plan, [t1, t2], [t1, t2]) do
791
- # This stops the mission, which will be automatically discarded
792
- t1.event(:stop).emit(nil)
793
- end
794
- end
795
-
796
- def test_gc_ignores_incoming_events
797
- Roby::Plan.logger.level = Logger::WARN
798
- a, b = prepare_plan :discover => 2, :model => SimpleTask
799
- a.signals(:stop, b, :start)
800
- a.start!
801
-
802
- process_events
803
- process_events
804
- assert(!a.plan)
805
- assert(!b.plan)
806
- assert(!b.event(:start).happened?)
807
- end
808
-
809
- # Test a setup where there is both pending tasks and running tasks. This
810
- # checks that #stop! is called on all the involved tasks. This tracks
811
- # problems related to bindings in the implementation of #garbage_collect:
812
- # the killed task bound to the Roby.once block must remain the same.
813
- def test_gc_stopping
814
- Roby::Plan.logger.level = Logger::WARN
815
- running_task = nil
816
- FlexMock.use do |mock|
817
- task_model = Class.new(Task) do
818
- event :start, :command => true
819
- event :stop do
820
- mock.stop(self)
821
- end
822
- end
823
-
824
- running_tasks = (1..5).map do
825
- task_model.new
826
- end
827
-
828
- plan.add(running_tasks)
829
- t1, t2 = Roby::Task.new, Roby::Task.new
830
- t1.depends_on t2
831
- plan.add(t1)
832
-
833
- running_tasks.each do |t|
834
- t.start!
835
- mock.should_receive(:stop).with(t).once
836
- end
837
-
838
- engine.garbage_collect
839
- process_events
840
-
841
- assert(!plan.include?(t1))
842
- assert(!plan.include?(t2))
843
- running_tasks.each do |t|
844
- assert(t.finishing?)
845
- t.emit(:stop)
846
- end
847
-
848
- engine.garbage_collect
849
- running_tasks.each do |t|
850
- assert(!plan.include?(t))
851
- end
852
- end
853
-
854
- ensure
855
- running_task.emit(:stop) if running_task && !running_task.finished?
856
- end
857
-
858
- def test_garbage_collect_events
859
- t = SimpleTask.new
860
- e1 = EventGenerator.new(true)
861
-
862
- plan.add_mission(t)
863
- plan.add(e1)
864
- assert_equal([e1], plan.unneeded_events.to_a)
865
- t.event(:start).signals e1
866
- assert_equal([], plan.unneeded_events.to_a)
867
-
868
- e2 = EventGenerator.new(true)
869
- plan.add(e2)
870
- assert_equal([e2], plan.unneeded_events.to_a)
871
- e1.forward_to e2
872
- assert_equal([], plan.unneeded_events.to_a)
873
-
874
- plan.remove_object(t)
875
- assert_equal([e1, e2].to_value_set, plan.unneeded_events)
876
-
877
- plan.add_permanent(e1)
878
- assert_equal([], plan.unneeded_events.to_a)
879
- plan.unmark_permanent(e1)
880
- assert_equal([e1, e2].to_value_set, plan.unneeded_events)
881
- plan.add_permanent(e2)
882
- assert_equal([], plan.unneeded_events.to_a)
883
- plan.unmark_permanent(e2)
884
- assert_equal([e1, e2].to_value_set, plan.unneeded_events)
885
- end
886
-
887
- def test_garbage_collect_weak_relations
888
- engine.run
889
-
890
- engine.execute do
891
- planning, planned, influencing = prepare_plan :discover => 3, :model => SimpleTask
892
-
893
- planned.planned_by planning
894
- influencing.depends_on planned
895
- planning.influenced_by influencing
896
-
897
- planned.start!
898
- planning.start!
899
- influencing.start!
900
- end
901
-
902
- engine.wait_one_cycle
903
- engine.wait_one_cycle
904
- engine.wait_one_cycle
905
-
906
- assert(plan.known_tasks.empty?)
907
- end
908
-
909
- def test_mission_failed
910
- model = Class.new(SimpleTask) do
911
- event :specialized_failure, :command => true
912
- forward :specialized_failure => :failed
913
- end
914
-
915
- task = prepare_plan :missions => 1, :model => model
916
- task.start!
917
- task.specialized_failure!
918
-
919
- error = Roby::Plan.check_failed_missions(plan).first.exception
920
- assert_kind_of(Roby::MissionFailedError, error)
921
- assert_equal(task.event(:specialized_failure).last, error.failure_point)
922
- assert_nothing_raised do
923
- Roby.format_exception error
924
- end
925
-
926
- # Makes teardown happy
927
- plan.remove_object(task)
928
- end
929
-
930
- def test_check_relations_structure
931
- r_t = TaskStructure.relation :TestRT
932
- r_e = EventStructure.relation :TestRE
933
-
934
- FlexMock.use do |mock|
935
- r_t.singleton_class.class_eval do
936
- define_method :check_structure do |plan|
937
- mock.checked_task_relation(plan)
938
- []
939
- end
940
- end
941
- r_e.singleton_class.class_eval do
942
- define_method :check_structure do |plan|
943
- mock.checked_event_relation(plan)
944
- []
945
- end
946
- end
947
-
948
- plan = Plan.new
949
- assert plan.relations.include?(r_t)
950
- assert plan.relations.include?(r_e)
951
-
952
- mock.should_receive(:checked_task_relation).with(plan).once
953
- mock.should_receive(:checked_event_relation).with(plan).once
954
- assert_equal(Hash.new, plan.check_structure)
955
- end
956
- ensure
957
- TaskStructure.remove_relation r_t if r_t
958
- EventStructure.remove_relation r_e if r_e
959
- end
960
-
961
- def test_forward_signal_ordering
962
- 100.times do
963
- stop_called = false
964
- source = SimpleTask.new(:id => 'source')
965
- target = Class.new(SimpleTask) do
966
- event :start do
967
- if !stop_called
968
- raise ArgumentError, "ordering failed"
969
- end
970
- emit :start
971
- end
972
- end.new(:id => 'target')
973
- plan.add_permanent(source)
974
- plan.add_permanent(target)
975
-
976
- source.signals :success, target, :start
977
- source.on :stop do
978
- stop_called = true
979
- end
980
- source.start!
981
- source.emit :success
982
- assert(target.running?)
983
- target.stop!
984
- end
985
- end
986
- end
987
-