roby 0.8.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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