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,638 +1,415 @@
1
- require 'test/unit'
2
- require 'utilrb/time/to_hms'
1
+ require 'minitest/spec'
2
+ require 'roby/test/assertions'
3
+ require 'flexmock/minitest'
4
+ require 'timecop'
5
+
6
+ # simplecov must be loaded FIRST. Only the files required after it gets loaded
7
+ # will be profiled !!!
8
+ if ENV['TEST_ENABLE_COVERAGE'] == '1' || ENV['TEST_COVERAGE_MODE']
9
+ mode = ENV['TEST_COVERAGE_MODE'] || 'simplecov'
10
+ begin
11
+ require mode
12
+ rescue LoadError => e
13
+ require 'roby'
14
+ Roby.warn "coverage is disabled because the code coverage gem cannot be loaded: #{e.message}"
15
+ rescue Exception => e
16
+ require 'roby'
17
+ Roby.warn "coverage is disabled: #{e.message}"
18
+ end
19
+ end
20
+
21
+ if ENV['TEST_ENABLE_PRY'] != '0'
22
+ begin
23
+ require 'pry'
24
+ rescue Exception
25
+ require 'roby'
26
+ Roby.warn "debugging is disabled because the 'pry' gem cannot be loaded"
27
+ end
28
+ end
29
+
3
30
  require 'roby'
4
- require 'utilrb/module/attr_predicate'
31
+
32
+ require 'roby/test/assertion'
33
+ require 'roby/test/error'
34
+ require 'roby/test/minitest_helpers'
35
+ require 'roby/test/execution_expectations'
36
+ require 'roby/test/validate_state_machine'
37
+ require 'roby/test/teardown_plans'
38
+
39
+ FlexMock.partials_are_based = true
5
40
 
6
41
  module Roby
42
+ # This module is defining common support for tests that need the Roby
43
+ # infrastructure
44
+ #
45
+ # It assumes that the tests are started using roby's test command. Tests
46
+ # using this module can NOT be started with only e.g. testrb.
47
+ #
48
+ # @see SelfTest
7
49
  module Test
8
- include Roby
9
- Unit = ::Test::Unit
10
-
11
- BASE_PORT = 1245
12
- DISCOVERY_SERVER = "druby://localhost:#{BASE_PORT}"
13
- REMOTE_PORT = BASE_PORT + 1
14
- LOCAL_PORT = BASE_PORT + 2
15
- REMOTE_SERVER = "druby://localhost:#{BASE_PORT + 3}"
16
- LOCAL_SERVER = "druby://localhost:#{BASE_PORT + 4}"
50
+ include Roby
51
+ include TeardownPlans
17
52
 
53
+ extend Logger::Hierarchy
54
+ extend Logger::Forward
18
55
 
19
- attr_reader :timings
20
- class << self
21
- attr_accessor :check_allocation_count
22
- end
56
+ BASE_PORT = 21000
57
+ DISCOVERY_SERVER = "druby://localhost:#{BASE_PORT}"
58
+ REMOTE_PORT = BASE_PORT + 1
59
+ LOCAL_PORT = BASE_PORT + 2
60
+ REMOTE_SERVER = "druby://localhost:#{BASE_PORT + 3}"
61
+ LOCAL_SERVER = "druby://localhost:#{BASE_PORT + 4}"
23
62
 
24
- # The plan used by the tests
63
+ # The plan used by the tests
25
64
  attr_reader :plan
26
65
  # The decision control component used by the tests
27
66
  attr_reader :control
28
- def engine; plan.engine end
29
67
 
30
- # Clear the plan and return it
31
- def new_plan
32
- plan.clear
33
- plan
34
- end
68
+ def execution_engine
69
+ plan.execution_engine if plan && plan.executable?
70
+ end
71
+
72
+ def execute(&block)
73
+ execution_engine.execute(&block)
74
+ end
75
+
76
+ # Clear the plan and return it
77
+ def new_plan
78
+ plan.clear
79
+ plan
80
+ end
81
+
82
+ def create_transaction
83
+ t = Roby::Transaction.new(plan)
84
+ @transactions << t
85
+ t
86
+ end
35
87
 
36
88
  def deprecated_feature
37
89
  Roby.enable_deprecation_warnings = false
90
+ flexmock(Roby).should_receive(:warn_deprecated).at_least.once
38
91
  yield
39
92
  ensure
40
93
  Roby.enable_deprecation_warnings = true
41
94
  end
42
95
 
43
- # a [collection, collection_backup] array of the collections saved
44
- # by #original_collections
45
- attr_reader :original_collections
46
-
47
- # Saves the current state of +obj+. This state will be restored by
48
- # #restore_collections. +obj+ must respond to #<< to add new elements
49
- # (hashes do not work whild arrays or sets do)
50
- def save_collection(obj)
51
- original_collections << [obj, obj.dup]
52
- end
53
-
54
- # Restors the collections saved by #save_collection to their previous state
55
- def restore_collections
56
- original_collections.each do |col, backup|
57
- col.clear
58
- if col.kind_of?(Hash)
59
- col.merge! backup
60
- else
61
- backup.each(&col.method(:<<))
62
- end
63
- end
64
- end
65
-
66
- def setup
67
- super if defined? super
68
-
69
- @console_logger ||= false
70
- @event_logger ||= false
71
- if !defined? Roby::State
72
- Roby.const_set(:State, StateSpace.new)
73
- else
74
- Roby::State.clear
75
- end
76
-
77
- @original_roby_logger_level = Roby.logger.level
78
- @timings = { :start => Time.now }
79
-
80
- @original_collections = []
81
- Thread.abort_on_exception = false
82
- @remote_processes = []
83
-
84
- Roby.app.setup_loggers
85
-
86
- if Test.check_allocation_count
87
- GC.start
88
- GC.disable
89
- end
90
-
91
- unless DRb.primary_server
92
- DRb.start_service 'druby://localhost:0'
93
- end
94
-
95
- if defined? Roby::Planning::Planner
96
- Roby::Planning::Planner.last_id = 0
97
- end
98
-
99
- @plan ||= Plan.new
100
- @control ||= DecisionControl.new
101
- if !plan.engine
102
- ExecutionEngine.new(@plan, @control)
103
- end
104
- plan.engine.gc_warning = false
105
-
106
- # Save and restore some arrays
107
- save_collection engine.propagation_handlers
108
- save_collection Roby::ExecutionEngine.propagation_handlers
109
- save_collection plan.structure_checks
110
- save_collection Roby::Plan.structure_checks
111
- save_collection engine.at_cycle_end_handlers
112
- save_collection Roby::EventGenerator.event_gathering
113
- Roby.app.abort_on_exception = true
114
- Roby.app.abort_on_application_exception = true
115
-
116
- save_collection engine.event_ordering
117
- save_collection engine.delayed_events
118
- save_collection plan.exception_handlers
119
- timings[:setup] = Time.now
120
-
121
- engine.at_cycle_end(&Test.method(:check_event_assertions))
122
- engine.finalizers << Test.method(:finalize_event_assertions)
123
- end
124
-
125
-
126
- def teardown_plan
127
- engine.at_cycle_end_handlers.delete(Test.method(:check_event_assertions))
128
- engine.finalizers.delete(Test.method(:finalize_event_assertions))
129
-
130
- old_gc_roby_logger_level = Roby.logger.level
131
- if debug_gc?
132
- Roby.logger.level = Logger::DEBUG
133
- end
134
-
135
- if !engine.running?
136
- engine.run
137
- end
138
-
139
- engine.quit
140
- engine.join
141
- plan.clear
142
-
143
- ensure
144
- Roby.logger.level = old_gc_roby_logger_level
145
- end
146
-
147
- def teardown
148
- timings[:quit] = Time.now
149
- teardown_plan
150
- timings[:teardown_plan] = Time.now
151
-
152
- stop_remote_processes
153
- DRb.stop_service if DRb.thread
154
-
155
- restore_collections
156
-
157
- # Clear all relation graphs in TaskStructure and EventStructure
158
- spaces = []
159
- if defined? Roby::TaskStructure
160
- spaces << Roby::TaskStructure
161
- end
162
- if defined? Roby::EventStructure
163
- spaces << Roby::EventStructure
164
- end
165
- spaces.each do |space|
166
- space.relations.each do |rel|
167
- vertices = rel.enum_for(:each_vertex).to_a
168
- unless vertices.empty?
169
- Roby.warn " the following vertices are still present in #{rel}: #{vertices.to_a}"
170
- vertices.each { |v| v.clear_vertex }
171
- end
172
- end
173
- end
174
-
175
- Roby::TaskStructure::Hierarchy.interesting_events.clear
176
- if defined? Roby::Application
177
- Roby.app.abort_on_exception = false
178
- Roby.app.abort_on_application_exception = false
179
- end
180
-
181
- if defined? Roby::Log
182
- Roby::Log.known_objects.clear
183
- end
184
-
185
- if Test.check_allocation_count
186
- require 'utilrb/objectstats'
187
- count = ObjectStats.count
188
- GC.start
189
- remains = ObjectStats.count
190
- Roby.warn "#{count} -> #{remains} (#{count - remains})"
191
- end
192
- timings[:end] = Time.now
193
-
194
- if display_timings?
195
- begin
196
- display_timings!
197
- rescue
198
- Roby.warn $!.full_message
199
- end
200
- end
201
-
202
- super if defined? super
203
-
204
- rescue Exception => e
205
- STDERR.puts "failed teardown: #{e.full_message}"
206
-
207
- ensure
208
- while engine.running?
209
- engine.quit
210
- engine.join rescue nil
211
- end
212
- plan.clear
213
- @plan = nil
214
-
215
- Roby.logger.level = @original_roby_logger_level
216
- self.console_logger = false
217
- self.event_logger = false
218
- end
219
-
220
- # Process pending events
221
- def process_events
222
- Roby.synchronize do
223
- engine.process_events
224
- end
225
- end
226
-
227
- # The list of children started using #remote_process
228
- attr_reader :remote_processes
229
-
230
- # Creates a set of tasks and returns them. Each task is given an unique
231
- # 'id' which allows to recognize it in a failed assertion.
232
- #
233
- # Known options are:
234
- # missions:: how many mission to create [0]
235
- # discover:: how many tasks should be discovered [0]
236
- # tasks:: how many tasks to create outside the plan [0]
237
- # model:: the task model [Roby::Task]
238
- # plan:: the plan to apply on [plan]
239
- #
240
- # The return value is [missions, discovered, tasks]
241
- # (t1, t2), (t3, t4, t5), (t6, t7) = prepare_plan :missions => 2,
242
- # :discover => 3, :tasks => 2
243
- #
244
- # An empty set is omitted
245
- # (t1, t2), (t6, t7) = prepare_plan :missions => 2, :tasks => 2
246
- #
247
- # If a set is a singleton, the only object of this singleton is returned
248
- # t1, (t6, t7) = prepare_plan :missions => 1, :tasks => 2
249
- #
250
- def prepare_plan(options)
251
- options = validate_options options,
252
- :missions => 0, :add => 0, :discover => 0, :tasks => 0,
253
- :permanent => 0,
254
- :model => Roby::Task, :plan => plan
255
-
256
- missions, permanent, added, tasks = [], [], [], []
257
- (1..options[:missions]).each do |i|
258
- options[:plan].add_mission(t = options[:model].new(:id => "mission-#{i}"))
259
- missions << t
260
- end
261
- (1..options[:permanent]).each do |i|
262
- options[:plan].add_permanent(t = options[:model].new(:id => "perm-#{i}"))
263
- permanent << t
264
- end
265
- (1..(options[:discover] + options[:add])).each do |i|
266
- options[:plan].add(t = options[:model].new(:id => "discover-#{i}"))
267
- added << t
268
- end
269
- (1..options[:tasks]).each do |i|
270
- tasks << options[:model].new(:id => "task-#{i}")
271
- end
272
-
273
- result = []
274
- [missions, permanent, added, tasks].each do |set|
275
- unless set.empty?
276
- set = *set
277
- result << set
278
- end
279
- end
280
- if result.size == 1 then result.first
281
- else result
282
- end
283
- end
284
-
285
- # Start a new process and saves its PID in #remote_processes. If a block is
286
- # given, it is called in the new child. #remote_process returns only after
287
- # this block has returned.
288
- def remote_process
289
- start_r, start_w= IO.pipe
290
- quit_r, quit_w = IO.pipe
291
- remote_pid = fork do
292
- begin
293
- start_r.close
294
- yield
295
- rescue Exception => e
296
- puts e.full_message
96
+ # a [collection, collection_backup] array of the collections saved
97
+ # by #original_collections
98
+ attr_reader :original_collections
99
+
100
+ # Saves the current state of +obj+. This state will be restored by
101
+ # #restore_collections. +obj+ must respond to #<< to add new elements
102
+ # (hashes do not work whild arrays or sets do)
103
+ def save_collection(obj)
104
+ original_collections << [obj, obj.dup]
105
+ end
106
+
107
+ # Restors the collections saved by #save_collection to their previous state
108
+ def restore_collections
109
+ original_collections.each do |col, backup|
110
+ col.clear
111
+ if col.kind_of?(Hash)
112
+ col.merge! backup
113
+ else
114
+ backup.each do |obj|
115
+ col << obj
116
+ end
297
117
  end
118
+ end
119
+ original_collections.clear
120
+ end
298
121
 
299
- start_w.write('OK')
300
- quit_r.read(2)
301
- end
302
- start_w.close
303
- result = start_r.read(2)
304
-
305
- remote_processes << [remote_pid, quit_w]
306
- remote_pid
307
-
308
- ensure
309
- # start_r.close
310
- end
311
-
312
- # Stop all the remote processes that have been started using #remote_process
313
- def stop_remote_processes
314
- remote_processes.reverse.each do |pid, quit_w|
315
- begin
316
- quit_w.write('OK')
317
- rescue Errno::EPIPE
318
- end
319
- begin
320
- Process.waitpid(pid)
321
- rescue Errno::ECHILD
322
- end
323
- end
324
- remote_processes.clear
325
- end
326
-
327
- # Exception raised in the block of assert_doesnt_timeout when the timeout
328
- # is reached
329
- class FailedTimeout < RuntimeError; end
330
-
331
- def assert_original_error(klass, localized_error_type = LocalizedError)
332
- old_level = Roby.logger.level
333
- Roby.logger.level = Logger::FATAL
334
- assert_nothing_raised do
335
- begin
336
- yield
337
- rescue Exception => e
338
- assert_kind_of(localized_error_type, e)
339
- assert_respond_to(e, :error)
340
- assert_kind_of(klass, e.error)
341
- end
342
- end
343
- ensure
344
- Roby.logger.level = old_level
345
- end
346
-
347
- # Checks that the given block returns within +seconds+ seconds
348
- def assert_doesnt_timeout(seconds, message = "watchdog #{seconds} failed")
349
- watched_thread = Thread.current
350
- watchdog = Thread.new do
351
- sleep(seconds)
352
- watched_thread.raise FailedTimeout
353
- end
354
-
355
- assert_block(message) do
356
- begin
357
- yield
358
- true
359
- rescue FailedTimeout
360
- ensure
361
- watchdog.kill
362
- watchdog.join
363
- end
364
- end
365
- end
366
-
367
- def assert_marshallable(object)
368
- begin
369
- Marshal.dump(object)
370
- true
371
- rescue TypeError
372
- end
373
- end
374
-
375
- # The console logger object. See #console_logger=
376
- attr_reader :console_logger
377
-
378
- attr_predicate :debug_gc?, true
379
- attr_predicate :display_timings?, true
380
- def display_timings!
381
- timings = self.timings.sort_by { |_, t| t }
382
- ref = timings[0].last
383
-
384
- format, header, times = "", [], []
385
- format << "%#{method_name.size}s"
386
- header << method_name
387
- times << ""
388
- timings.each do |name, time|
389
- name = name.to_s
390
- time = "%.2f" % [time - ref]
391
-
392
- col_size = [name.size, time.size].max
393
- format << " % #{col_size}s"
394
- header << name
395
- times << time
396
- end
397
-
398
- puts
399
- puts format % header
400
- puts format % times
401
- end
402
-
403
- # Enable display of all plan events on the console
404
- def console_logger=(value)
405
- if value && !@console_logger
406
- require 'roby/log/console'
407
- @console_logger = Roby::Log::ConsoleLogger.new(STDERR)
408
- Roby::Log.add_logger console_logger
409
- elsif @console_logger
410
- Roby::Log.remove_logger console_logger
411
- @console_logger = nil
412
- end
413
- end
414
-
415
- attr_reader :event_logger
416
- def event_logger=(value)
417
- if value && !@event_logger
418
- require 'roby/log/file'
419
- logfile = @method_name + ".log"
420
- logger = Roby::Log::FileLogger.new(logfile)
421
- logger.stats_mode = false
422
- Roby::Log.add_logger logger
423
- @event_logger = logger
424
- elsif !value && @event_logger
425
- Roby::Log.remove_logger @event_logger
426
- @event_logger = nil
122
+ attr_reader :app
123
+
124
+ def setup
125
+ @app = Roby.app
126
+ @app.development_mode = false
127
+ Roby.app.reload_config
128
+ @log_levels = Hash.new
129
+ @transactions = Array.new
130
+
131
+ if !@plan
132
+ @plan = Roby.app.plan
133
+ end
134
+ register_plan(@plan)
135
+
136
+ super
137
+
138
+ @console_logger ||= false
139
+ @event_logger ||= false
140
+
141
+ @original_roby_logger_level = Roby.logger.level
142
+
143
+ @original_collections = []
144
+ Thread.abort_on_exception = false
145
+ @remote_processes = []
146
+
147
+ Roby.app.log_server = false
148
+
149
+ plan.execution_engine.gc_warning = false
150
+
151
+ @watched_events = nil
152
+ @handler_ids = Array.new
153
+ end
154
+
155
+ # @deprecated use {Assertions#capture_log} instead
156
+ def inhibit_fatal_messages(&block)
157
+ Roby.warn_deprecated "##{__method__} is deprecated, use #capture_log instead"
158
+ with_log_level(Roby, Logger::FATAL, &block)
159
+ end
160
+
161
+ # @deprecated use {Assertions#capture_log} instead
162
+ def set_log_level(log_object, level)
163
+ Roby.warn_deprecated "#set_log_level is deprecated, use #capture_log instead"
164
+ if log_object.respond_to?(:logger)
165
+ log_object = log_object.logger
427
166
  end
167
+ @log_levels[log_object] ||= log_object.level
168
+ log_object.level = level
428
169
  end
429
170
 
430
- def wait_thread_stopped(thread)
431
- while !thread.stop?
432
- sleep(0.1)
433
- raise "#{thread} died" unless thread.alive?
434
- end
435
- end
436
-
437
- def display_event_structure(object, relation, indent = " ")
438
- result = object.to_s
439
- object.history.each do |event|
440
- result << "#{indent}#{event.time.to_hms} #{event}"
441
- end
442
- children = object.child_objects(relation)
443
- unless children.empty?
444
- result << " ->\n" << indent
445
- children.each do |child|
446
- result << display_event_structure(child, relation, indent + " ")
447
- end
448
- end
449
-
450
- result
451
- end
452
-
453
- @event_assertions = []
454
- @waiting_threads = []
455
-
456
- ASSERT_ANY_EVENTS_TLS = :assert_any_events
457
-
458
- class << self
459
- # A [thread, cv, positive, negative] list of event assertions
460
- attr_reader :event_assertions
171
+ # @deprecated use {Assertions#capture_log} instead
172
+ def reset_log_levels(warn_deprecated: true)
173
+ if warn_deprecated
174
+ Roby.warn_deprecated "##{__method__} is deprecated, use #capture_log instead"
175
+ end
176
+ @log_levels.each do |log_object, level|
177
+ log_object.level = level
178
+ end
179
+ @log_levels.clear
461
180
  end
462
181
 
463
- # Tests for events in +positive+ and +negative+ and returns
464
- # the set of failing events if the assertion has finished.
465
- # If the set is empty, it means that the assertion finished
466
- # successfully
467
- def self.assert_any_event_result(positive, negative)
468
- if positive_ev = positive.find { |ev| ev.happened? }
469
- return false, "#{positive_ev} happened"
182
+ # @deprecated use {Assertions#capture_log} instead
183
+ def with_log_level(log_object, level)
184
+ Roby.warn_deprecated "##{__method__} is deprecated, use #capture_log instead"
185
+ if log_object.respond_to?(:logger)
186
+ log_object = log_object.logger
187
+ end
188
+ current_level = log_object.level
189
+ log_object.level = level
190
+
191
+ yield
192
+
193
+ ensure
194
+ if current_level
195
+ log_object.level = current_level
470
196
  end
471
- failure = negative.find_all { |ev| ev.happened? }
472
- unless failure.empty?
473
- return true, "#{failure} happened"
197
+ end
198
+
199
+ def teardown
200
+ Timecop.return
201
+
202
+ @transactions.each do |trsc|
203
+ if !trsc.finalized?
204
+ trsc.discard_transaction
205
+ end
474
206
  end
207
+ teardown_registered_plans
475
208
 
476
- if positive.all? { |ev| ev.unreachable? }
477
- positive.each do |ev|
478
- Robot.info "#{ev} is unreachable because of the following emission:"
479
- Roby.log_exception(ev.unreachability_reason, Robot.logger, :info)
209
+ if @handler_ids && execution_engine
210
+ @handler_ids.each do |handler_id|
211
+ execution_engine.remove_propagation_handler(handler_id)
480
212
  end
481
- return true, "all positive events are unreachable"
482
213
  end
483
214
 
484
- nil
215
+ # Plan teardown would have disconnected the peers already
216
+ stop_remote_processes
217
+
218
+ restore_collections
219
+
220
+ if defined? Roby::Application
221
+ Roby.app.abort_on_exception = false
222
+ Roby.app.abort_on_application_exception = true
223
+ end
224
+
225
+ super
226
+
227
+ ensure
228
+ reset_log_levels(warn_deprecated: false)
229
+ clear_registered_plans
230
+
231
+ if @original_roby_logger_level
232
+ Roby.logger.level = @original_roby_logger_level
233
+ end
234
+ end
235
+
236
+ # Process pending events
237
+ def process_events(timeout: 2, enable_scheduler: nil, join_all_waiting_work: true, raise_errors: true, garbage_collect_pass: true, &caller_block)
238
+ Roby.warn_deprecated "Test#process_events is deprecated, use #expect_execution instead"
239
+ exceptions = Array.new
240
+ registered_plans.each do |p|
241
+ engine = p.execution_engine
242
+
243
+ begin
244
+ engine.start_new_cycle
245
+ errors =
246
+ begin
247
+ current_scheduler_state = engine.scheduler.enabled?
248
+ if !enable_scheduler.nil?
249
+ engine.scheduler.enabled = enable_scheduler
250
+ end
251
+
252
+ engine.process_events(garbage_collect_pass: garbage_collect_pass, &caller_block)
253
+ ensure
254
+ engine.scheduler.enabled = current_scheduler_state
255
+ end
256
+
257
+ if join_all_waiting_work
258
+ engine.join_all_waiting_work(timeout: timeout)
259
+ end
260
+
261
+ exceptions.concat(errors.exceptions)
262
+ engine.cycle_end(Hash.new)
263
+ caller_block = nil
264
+ end while engine.has_waiting_work? && join_all_waiting_work
265
+ end
266
+
267
+ if raise_errors && !exceptions.empty?
268
+ if exceptions.size == 1
269
+ e = exceptions.first
270
+ raise e.exception
271
+ else
272
+ raise SynchronousEventProcessingMultipleErrors.new(exceptions.map(&:exception))
273
+ end
274
+ end
485
275
  end
486
276
 
487
- # This method is inserted in the control thread to implement
488
- # Assertions#assert_events
489
- def self.check_event_assertions
490
- event_assertions.delete_if do |thread, cv, positive, negative|
491
- error, result = Test.assert_any_event_result(positive, negative)
492
- if !error.nil?
493
- thread[ASSERT_ANY_EVENTS_TLS] = [error, result]
494
- cv.broadcast
495
- true
277
+ # Repeatedly process events until a condition is met
278
+ #
279
+ # @yieldreturn [Boolean] true if the condition is met, false otherwise
280
+ #
281
+ # @param (see #process_events)
282
+ def process_events_until(timeout: 5, join_all_waiting_work: false, **options)
283
+ Roby.warn_deprecated "Test#process_events_until is deprecated, use #expect_execution.to { achieve { ... } } instead"
284
+ start = Time.now
285
+ while !yield
286
+ now = Time.now
287
+ remaining = timeout - (now - start)
288
+ if remaining < 0
289
+ flunk("failed to reach condition #{proc} within #{timeout} seconds")
496
290
  end
291
+ process_events(timeout: remaining, join_all_waiting_work: join_all_waiting_work, **options)
292
+ sleep 0.01
497
293
  end
498
294
  end
499
295
 
500
- def self.finalize_event_assertions
501
- check_event_assertions
502
- event_assertions.dup.each do |thread, *_|
503
- thread.raise ControlQuitError
296
+ # Use to call the original method on a partial mock
297
+ def flexmock_call_original(object, method, *args, &block)
298
+ Test.warn "#flexmock_call_original is deprecated, use #flexmock_invoke_original instead"
299
+ flexmock_invoke_original(object, method, *args, &block)
300
+ end
301
+
302
+ # Use to call the original method on a partial mock
303
+ def flexmock_invoke_original(object, method, *args, &block)
304
+ object.instance_variable_get(:@flexmock_proxy).proxy.flexmock_invoke_original(method, args, &block)
305
+ end
306
+
307
+ # The list of children started using #remote_process
308
+ attr_reader :remote_processes
309
+
310
+ # Creates a set of tasks and returns them. Each task is given an unique
311
+ # 'id' which allows to recognize it in a failed assertion.
312
+ #
313
+ # Known options are:
314
+ # missions:: how many mission to create [0]
315
+ # discover:: how many tasks should be discovered [0]
316
+ # tasks:: how many tasks to create outside the plan [0]
317
+ # model:: the task model [Roby::Task]
318
+ # plan:: the plan to apply on [plan]
319
+ #
320
+ # The return value is [missions, discovered, tasks]
321
+ # (t1, t2), (t3, t4, t5), (t6, t7) = prepare_plan missions: 2,
322
+ # discover: 3, tasks: 2
323
+ #
324
+ # An empty set is omitted
325
+ # (t1, t2), (t6, t7) = prepare_plan missions: 2, tasks: 2
326
+ #
327
+ # If a set is a singleton, the only object of this singleton is returned
328
+ # t1, (t6, t7) = prepare_plan missions: 1, tasks: 2
329
+ #
330
+ def prepare_plan(options)
331
+ options = validate_options options,
332
+ missions: 0, add: 0, discover: 0, tasks: 0,
333
+ permanent: 0,
334
+ model: Roby::Task, plan: plan
335
+
336
+ missions, permanent, added, tasks = [], [], [], []
337
+ (1..options[:missions]).each do |i|
338
+ options[:plan].add_mission_task(t = options[:model].new(id: "mission-#{i}"))
339
+ missions << t
340
+ end
341
+ (1..options[:permanent]).each do |i|
342
+ options[:plan].add_permanent_task(t = options[:model].new(id: "perm-#{i}"))
343
+ permanent << t
344
+ end
345
+ (1..(options[:discover] + options[:add])).each do |i|
346
+ options[:plan].add(t = options[:model].new(id: "discover-#{i}"))
347
+ added << t
348
+ end
349
+ (1..options[:tasks]).each do |i|
350
+ tasks << options[:model].new(id: "task-#{i}")
351
+ end
352
+
353
+ result = []
354
+ [missions, permanent, added, tasks].each do |set|
355
+ unless set.empty?
356
+ result << set
357
+ end
504
358
  end
359
+
360
+ result = result.map do |set|
361
+ if set.size == 1 then set.first
362
+ else set
363
+ end
364
+ end
365
+
366
+ if result.size == 1
367
+ return result.first
368
+ end
369
+ return *result
505
370
  end
506
371
 
507
- module Assertions
508
- # Wait for any event in +positive+ to happen. If +negative+ is
509
- # non-empty, any event happening in this set will make the
510
- # assertion fail. If events in +positive+ are task events, the
511
- # :stop events of the corresponding tasks are added to negative
512
- # automatically.
513
- #
514
- # If a block is given, it is called from within the control thread
515
- # after the checks are in place
516
- #
517
- # So, to check that a task fails, do
518
- #
519
- # assert_events(task.event(:fail)) do
520
- # task.start!
521
- # end
522
- #
523
- def assert_any_event(positive, negative = [], msg = nil, &block)
524
- control_priority do
525
- engine.waiting_threads << Thread.current
526
- Roby.condition_variable(false) do |cv|
527
- positive = Array[*positive].to_value_set
528
- negative = Array[*negative].to_value_set
529
-
530
- unreachability_reason = ValueSet.new
531
- Roby.synchronize do
532
- positive.each do |ev|
533
- ev.if_unreachable(true) do |reason|
534
- unreachability_reason << reason if reason
535
- end
536
- end
537
-
538
- error, result = Test.assert_any_event_result(positive, negative)
539
- if error.nil?
540
- this_thread = Thread.current
541
-
542
- Test.event_assertions << [this_thread, cv, positive, negative]
543
- engine.once(&block) if block_given?
544
- begin
545
- cv.wait(Roby.global_lock)
546
- ensure
547
- Test.event_assertions.delete_if { |thread, _| thread == this_thread }
548
- end
549
-
550
- error, result = this_thread[ASSERT_ANY_EVENTS_TLS]
551
- end
552
-
553
- if error
554
- if !unreachability_reason.empty?
555
- msg = unreachability_reason.map do |reason|
556
- if reason.respond_to?(:context)
557
- context = (reason.context || []).map do |obj|
558
- if obj.kind_of?(Exception)
559
- obj.full_message
560
- else
561
- obj.to_s
562
- end
563
- end
564
- reason.to_s + context.join("\n ")
565
- end
566
- end
567
- msg.join("\n ")
568
-
569
- flunk("#{msg} all positive events are unreachable for the following reason:\n #{msg}")
570
- elsif msg
571
- flunk("#{msg} failed: #{result}")
572
- else
573
- flunk(result)
574
- end
575
- end
576
- end
577
- end
578
- end
579
- ensure
580
- engine.waiting_threads.delete(Thread.current)
581
- end
582
-
583
- # Starts +task+ and checks it succeeds
584
- def assert_succeeds(task, *args)
585
- control_priority do
586
- if !task.kind_of?(Roby::Task)
587
- engine.execute do
588
- plan.add_mission(task = planner.send(task, *args))
589
- end
590
- end
591
-
592
- assert_any_event([task.event(:success)], [], nil) do
593
- plan.add_permanent(task)
594
- task.start! if task.pending?
595
- yield if block_given?
596
- end
597
- end
598
- end
599
-
600
- def control_priority
601
- if !engine.thread
602
- return yield
372
+ # Start a new process and saves its PID in #remote_processes. If a block is
373
+ # given, it is called in the new child. #remote_process returns only after
374
+ # this block has returned.
375
+ def remote_process
376
+ start_r, start_w= IO.pipe
377
+ quit_r, quit_w = IO.pipe
378
+ remote_pid = fork do
379
+ begin
380
+ start_r.close
381
+ yield
382
+ rescue Exception => e
383
+ puts e.full_message
603
384
  end
604
385
 
605
- old_priority = Thread.current.priority
606
- Thread.current.priority = engine.thread.priority + 1
607
-
608
- yield
609
- ensure
610
- Thread.current.priority = old_priority if old_priority
611
- end
612
-
613
- # This assertion fails if the relative error between +found+ and
614
- # +expected+is more than +error+
615
- def assert_relative_error(expected, found, error, msg = "")
616
- if expected == 0
617
- assert_in_delta(0, found, error, "comparing #{found} to #{expected} in #{msg}")
618
- else
619
- assert_in_delta(0, (found - expected) / expected, error, "comparing #{found} to #{expected} in #{msg}")
620
- end
621
- end
622
-
623
- # This assertion fails if +found+ and +expected+ are more than +dl+
624
- # meters apart in the x, y and z coordinates, or +dt+ radians apart
625
- # in angles
626
- def assert_same_position(expected, found, dl = 0.01, dt = 0.01, msg = "")
627
- assert_relative_error(expected.x, found.x, dl, msg)
628
- assert_relative_error(expected.y, found.y, dl, msg)
629
- assert_relative_error(expected.z, found.z, dl, msg)
630
- assert_relative_error(expected.yaw, found.yaw, dt, msg)
631
- assert_relative_error(expected.pitch, found.pitch, dt, msg)
632
- assert_relative_error(expected.roll, found.roll, dt, msg)
633
- end
634
- end
386
+ start_w.write('OK')
387
+ quit_r.read(2)
388
+ end
389
+ start_w.close
390
+ result = start_r.read(2)
391
+
392
+ remote_processes << [remote_pid, quit_w]
393
+ remote_pid
394
+
395
+ ensure
396
+ # start_r.close
397
+ end
635
398
 
399
+ # Stop all the remote processes that have been started using #remote_process
400
+ def stop_remote_processes
401
+ remote_processes.reverse.each do |pid, quit_w|
402
+ begin
403
+ quit_w.write('OK')
404
+ rescue Errno::EPIPE
405
+ end
406
+ begin
407
+ Process.waitpid(pid)
408
+ rescue Errno::ECHILD
409
+ end
410
+ end
411
+ remote_processes.clear
412
+ end
636
413
  end
637
414
  end
638
415