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
@@ -0,0 +1,149 @@
1
+ module Roby
2
+ module Queries
3
+ # Object that allows to specify generalized matches on a
4
+ # Roby::LocalizedError object
5
+ class LocalizedErrorMatcher < MatcherBase
6
+ # @return [Class] the exception class that should be matched. It
7
+ # must be a subclass of LocalizedError, and is LocalizedError by
8
+ # default
9
+ attr_reader :model
10
+ # @return [#===] the object that will be used to match the error
11
+ # origin
12
+ attr_reader :failure_point_matcher
13
+ # @return [#===,nil] match object to validate the exception's
14
+ # ExeptionBase#original_exceptions
15
+ attr_reader :original_exception_model
16
+
17
+ def initialize
18
+ super
19
+ @model = LocalizedError
20
+ @failure_point_matcher = Queries.any
21
+ @original_exception_model = nil
22
+ end
23
+
24
+ # Specifies which subclass of LocalizedError this matcher should
25
+ # look for
26
+ # @return self
27
+ def with_model(model)
28
+ @model = model
29
+ self
30
+ end
31
+
32
+ # Specifies that the exception object should have an
33
+ # original_exception registered of the given model
34
+ #
35
+ # Set to nil to allow for no original exception at all
36
+ def with_original_exception(model)
37
+ if model.respond_to?(:exception_matcher)
38
+ @original_exception_model = model.exception_matcher
39
+ else
40
+ @original_exception_model = model
41
+ end
42
+ self
43
+ end
44
+
45
+ # Specifies a match on the error origin
46
+ #
47
+ # The resulting match is extended, i.e. a task matcher will match
48
+ # the origin's task event if the origin itself is an event.
49
+ #
50
+ # @return self
51
+ def with_origin(plan_object_matcher)
52
+ @failure_point_matcher = plan_object_matcher.match
53
+ if failure_point_matcher.respond_to?(:generalized?) && !plan_object_matcher.respond_to?(:generalized?)
54
+ failure_point_matcher.generalized
55
+ end
56
+ self
57
+ end
58
+
59
+ # @return [Boolean] true if the given execution exception object
60
+ # matches self, false otherwise
61
+ def ===(exception)
62
+ if !(model === exception)
63
+ return false
64
+ end
65
+
66
+ if original_exception_model
67
+ original_exception = exception.original_exceptions.
68
+ find { |e| original_exception_model === e }
69
+ if !original_exception
70
+ return false
71
+ end
72
+ end
73
+
74
+ if !exception.failed_task
75
+ if !(failure_point_matcher === exception.failed_generator)
76
+ return false
77
+ end
78
+ elsif failure_point_matcher.respond_to?(:task_matcher)
79
+ if exception.failed_generator
80
+ return false if !(failure_point_matcher === exception.failed_generator)
81
+ else return false
82
+ end
83
+ else
84
+ return false if !(failure_point_matcher === exception.failed_task)
85
+ end
86
+
87
+ original_exception || true
88
+ end
89
+
90
+ def describe_failed_match(exception)
91
+ if !(model === exception)
92
+ return "exception model #{exception} does not match #{model}"
93
+ end
94
+
95
+ if original_exception_model
96
+ original_exception = exception.original_exceptions.
97
+ find { |e| original_exception_model === e }
98
+ if !original_exception
99
+ if exception.original_exceptions.empty?
100
+ return "expected one of the original exceptions to match #{original_exception_model}, but none are registered"
101
+ else
102
+ return "expected one of the original exceptions to match #{original_exception_model}, but got #{exception.original_exceptions.map(&:to_s).join(", ")}"
103
+ end
104
+ end
105
+ end
106
+
107
+ if !exception.failed_task
108
+ if !(failure_point_matcher === exception.failed_generator)
109
+ return "failure point #{exception.failed_generator} does not match #{failure_point_matcher}"
110
+ end
111
+ elsif failure_point_matcher.respond_to?(:task_matcher)
112
+ if exception.failed_generator
113
+ if !(failure_point_matcher === exception.failed_generator)
114
+ return "failure point #{exception.failed_generator} does not match #{failure_point_matcher}"
115
+ end
116
+ else
117
+ return "exception reports no failure generator but was expected to"
118
+ end
119
+ elsif !(failure_point_matcher === exception.failed_task)
120
+ return "failure point #{exception.failed_task} does not match #{failure_point_matcher}"
121
+ end
122
+ nil
123
+ end
124
+
125
+ def to_s
126
+ description = "#{model}.with_origin(#{failure_point_matcher})"
127
+ if original_exception_model
128
+ description.concat(".with_original_exception(#{original_exception_model})")
129
+ end
130
+ description
131
+ end
132
+
133
+ def matches_task?(task)
134
+ if failure_point_matcher.respond_to?(:task_matcher)
135
+ failure_point_matcher.task_matcher == task
136
+ else failure_point_matcher === task
137
+ end
138
+ end
139
+
140
+ match_predicate :fatal?
141
+
142
+ def to_execution_exception_matcher
143
+ Roby::Queries::ExecutionExceptionMatcher.new.with_exception(self)
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+
@@ -0,0 +1,107 @@
1
+ module Roby
2
+ module Queries
3
+ class MatcherBase
4
+ # Returns true if calling #filter with a task set and a relevant
5
+ # index will return the exact query result or not
6
+ def indexed_query?; false end
7
+
8
+ # Enumerates all tasks of +plan+ which match this TaskMatcher object
9
+ #
10
+ # It is O(N). You should prefer use Query which uses the plan's task
11
+ # indexes, thus leading to O(1) in simple cases.
12
+ def each(plan)
13
+ return enum_for(__method__, plan) if !block_given?
14
+ plan.each_task do |t|
15
+ yield(t) if self === t
16
+ end
17
+ self
18
+ end
19
+
20
+ # Negates this predicate
21
+ #
22
+ # The returned task matcher will yield tasks that are *not* matched by
23
+ # +self+
24
+ def negate; NotMatcher.new(self) end
25
+ # AND-combination of two predicates
26
+ #
27
+ # The returned task matcher will yield tasks that are matched by both
28
+ # predicates.
29
+ def &(other); AndMatcher.new(self, other) end
30
+ # OR-combination of two predicates
31
+ #
32
+ # The returned task matcher will yield tasks that match either one
33
+ # predicate or the other.
34
+ def |(other); OrMatcher.new(self, other) end
35
+
36
+ # Set of predicates that should be true for the object
37
+ # @return [Array<Symbol>]
38
+ attr_reader :predicates
39
+
40
+ # Set of predicats that should be false for the object
41
+ #
42
+ # The predicates are predicate method names (e.g. 'executable' for #executable?)
43
+ #
44
+ # @return [Array<Symbol>]
45
+ attr_reader :neg_predicates
46
+
47
+ class << self
48
+ def declare_class_methods(*names) # :nodoc:
49
+ names.each do |name|
50
+ raise "no instance method #{name} on #{self}" unless method_defined?(name)
51
+ singleton_class.send(:define_method, name) do |*args|
52
+ self.new.send(name, *args)
53
+ end
54
+ end
55
+ end
56
+
57
+ def match_predicate(name)
58
+ method_name = name.to_s.gsub(/\?$/, '')
59
+ class_eval <<-EOD, __FILE__, __LINE__+1
60
+ def #{method_name}
61
+ if neg_predicates.include?(:#{name})
62
+ raise ArgumentError, "trying to match (#{name} & !#{name})"
63
+ end
64
+ predicates << :#{name}
65
+ self
66
+ end
67
+ def not_#{method_name}
68
+ if predicates.include?(:#{name})
69
+ raise ArgumentError, "trying to match (#{name} & !#{name})"
70
+ end
71
+ neg_predicates << :#{name}
72
+ self
73
+ end
74
+ EOD
75
+ declare_class_methods(method_name, "not_#{method_name}")
76
+ end
77
+
78
+ # For each name in +names+, define a #name and a #not_name method.
79
+ # If the first is called, the matcher will match only tasks whose
80
+ # #name? method returns true. If the second is called, the
81
+ # opposite will be done.
82
+ def match_predicates(*names)
83
+ names.each do |name|
84
+ match_predicate(name)
85
+ end
86
+ end
87
+ end
88
+
89
+ # The {#match} method is used to convert any object to the
90
+ # corresponding Query object. For instance, Models::TaskEvent#match
91
+ # returns the corresponding TaskEventGeneratorMatcher.
92
+ #
93
+ # For matchers, it returns self
94
+ def match
95
+ self
96
+ end
97
+
98
+ # Describe a failed match in a human-readable way
99
+ #
100
+ # It is meant to help debugging in tests
101
+ #
102
+ # @return [nil,String]
103
+ def describe_failed_match(exception)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,27 @@
1
+ module Roby
2
+ module Queries
3
+ # Implementation of a singleton object that matches no other object
4
+ module None
5
+ # @return [Boolean] match operator, always returns false
6
+ def self.===(other)
7
+ false
8
+ end
9
+
10
+ class DRoby
11
+ def proxy(peer)
12
+ Queries.none
13
+ end
14
+ end
15
+ def self.droby_dump(peer)
16
+ DRoby.new
17
+ end
18
+ end
19
+
20
+ # @return [None] an object that matches nothing
21
+ def self.none
22
+ None
23
+ end
24
+ end
25
+ end
26
+
27
+
@@ -0,0 +1,30 @@
1
+ module Roby
2
+ module Queries
3
+
4
+ # Negate a given task-matching predicate
5
+ #
6
+ # This matcher will match if the underlying predicate does not match.
7
+ class NotMatcher < MatcherBase
8
+ # Create a new TaskMatcher which matches if and only if +op+ does not
9
+ def initialize(op)
10
+ @op = op
11
+ end
12
+
13
+ # Filters as much as non-matching tasks as possible out of +task_set+,
14
+ # based on the information in +task_index+
15
+ def filter(initial_set, task_index)
16
+ # WARNING: the value returned by filter is a SUPERSET of the
17
+ # possible values for the query. Therefore, the result of
18
+ # NegateTaskMatcher#filter is NOT
19
+ #
20
+ # initial_set - @op.filter(...)
21
+ initial_set
22
+ end
23
+
24
+ # True if the task matches at least one of the underlying predicates
25
+ def ===(task)
26
+ !(@op === task)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,8 @@
1
+ module Roby
2
+ module Queries
3
+ # Base class for matchers that are built as operations over other
4
+ # matchers (e.g. 'or', 'not')
5
+ class OpMatcher
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,30 @@
1
+ module Roby
2
+ module Queries
3
+
4
+ # Combines multiple task matching predicates through a OR boolean operator.
5
+ # I.e. it will match if any of the underlying predicates match.
6
+ class OrMatcher < MatcherBase
7
+ # Create a new OrMatcher object combining the given predicates.
8
+ def initialize(*ops)
9
+ @ops = ops
10
+ end
11
+
12
+ # Overload of TaskMatcher#filter
13
+ def filter(task_set, task_index)
14
+ result = Set.new
15
+ for child in @ops
16
+ result.merge child.filter(task_set, task_index)
17
+ end
18
+ result
19
+ end
20
+
21
+ # Add a new predicate to the combination
22
+ def <<(op); @ops << op end
23
+
24
+ def ===(task)
25
+ @ops.any? { |op| op === task }
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,363 @@
1
+ module Roby
2
+ module Queries
3
+ # Predicate that matches characteristics on a plan object
4
+ class PlanObjectMatcher < MatcherBase
5
+ # @api private
6
+ #
7
+ # The actual instance that should match
8
+ #
9
+ # @return [nil,Object]
10
+ attr_reader :instance
11
+
12
+ # @api private
13
+ #
14
+ # A set of models that should be provided by the object
15
+ #
16
+ # @return [Array<Class>]
17
+ attr_reader :model
18
+
19
+ # @api private
20
+ #
21
+ # Set of owners that the object should have
22
+ #
23
+ # @return [Array<DRobyID>]
24
+ attr_reader :owners
25
+
26
+ # @api private
27
+ #
28
+ # Set of predicates that should be true on the object, and for which
29
+ # the index maintains a set of objects for which it is true
30
+ #
31
+ # @return [Array<Symbol>]
32
+ attr_reader :indexed_predicates
33
+
34
+ # @api private
35
+ #
36
+ # Set of predicates that should be false on the object, and for which
37
+ # the index maintains a set of objects for which it is true
38
+ #
39
+ # @return [Array<Symbol>]
40
+ attr_reader :indexed_neg_predicates
41
+
42
+ # @api private
43
+ #
44
+ # Per-relation list of in-edges that the matched object is expected to have
45
+ #
46
+ # @return [Hash]
47
+ attr_reader :parents
48
+
49
+ # @api private
50
+ #
51
+ # Per relation list of out-edges that the matched object is expected to have
52
+ #
53
+ # @return [Hash]
54
+ attr_reader :children
55
+
56
+ # Initializes an empty TaskMatcher object
57
+ def initialize(instance = nil)
58
+ @instance = instance
59
+ @indexed_query = !@instance
60
+ @model = Array.new
61
+ @predicates = Array.new
62
+ @neg_predicates = Array.new
63
+ @indexed_predicates = Array.new
64
+ @indexed_neg_predicates = Array.new
65
+ @owners = Array.new
66
+ @parents = Hash.new
67
+ @children = Hash.new
68
+ end
69
+
70
+ # Match an instance explicitely
71
+ def with_instance(instance)
72
+ @instance = instance
73
+ @indexed_query = false
74
+ self
75
+ end
76
+
77
+ # Filters on ownership
78
+ #
79
+ # Matches if the object is owned by the listed peers.
80
+ #
81
+ # Use #self_owned to match if it is owned by the local plan manager.
82
+ def owned_by(*ids)
83
+ @owners |= ids
84
+ self
85
+ end
86
+
87
+ # Filters locally-owned tasks
88
+ #
89
+ # Matches if the object is owned by the local plan manager.
90
+ def self_owned
91
+ predicates << :self_owned?
92
+ self
93
+ end
94
+
95
+ # Filters out locally-owned tasks
96
+ #
97
+ # Matches if the object is owned by the local plan manager.
98
+ def not_self_owned
99
+ neg_predicates << :self_owned?
100
+ self
101
+ end
102
+
103
+ # Filters on the task model
104
+ #
105
+ # Will match if the task is an instance of +model+ or one of its
106
+ # subclasses.
107
+ def with_model(model)
108
+ @model = Array(model)
109
+ self
110
+ end
111
+
112
+ class << self
113
+ # @api private
114
+ def match_predicate(name, positive_index = nil, negative_index = nil)
115
+ method_name = name.to_s.gsub(/\?$/, '')
116
+ if Index::PREDICATES.include?(name)
117
+ indexed_predicate = true
118
+ positive_index ||= [["#{name}"], []]
119
+ negative_index ||= [[], ["#{name}"]]
120
+ end
121
+ positive_index ||= [[], []]
122
+ negative_index ||= [[], []]
123
+ class_eval <<-EOD, __FILE__, __LINE__+1
124
+ def #{method_name}
125
+ if neg_predicates.include?(:#{name})
126
+ raise ArgumentError, "trying to match (#{name} & !#{name})"
127
+ end
128
+ #{"@indexed_query = false" if !indexed_predicate}
129
+ predicates << :#{name}
130
+ #{if !positive_index[0].empty? then ["indexed_predicates", *positive_index[0]].join(" << :") end}
131
+ #{if !positive_index[1].empty? then ["indexed_neg_predicates", *positive_index[1]].join(" << :") end}
132
+ self
133
+ end
134
+ def not_#{method_name}
135
+ if predicates.include?(:#{name})
136
+ raise ArgumentError, "trying to match (#{name} & !#{name})"
137
+ end
138
+ #{"@indexed_query = false" if !indexed_predicate}
139
+ neg_predicates << :#{name}
140
+ #{if !negative_index[0].empty? then ["indexed_predicates", *negative_index[0]].join(" << :") end}
141
+ #{if !negative_index[1].empty? then ["indexed_neg_predicates", *negative_index[1]].join(" << :") end}
142
+ self
143
+ end
144
+ EOD
145
+ declare_class_methods(method_name, "not_#{method_name}")
146
+ end
147
+ end
148
+
149
+ ##
150
+ # :method: executable
151
+ #
152
+ # Matches if the object is executable
153
+ #
154
+ # See also #not_executable, PlanObject#executable?
155
+
156
+ ##
157
+ # :method: not_executable
158
+ #
159
+ # Matches if the object is not executable
160
+ #
161
+ # See also #executable, PlanObject#executable?
162
+
163
+ match_predicates :executable?
164
+
165
+ declare_class_methods :with_model, :owned_by, :self_owned
166
+
167
+ # Helper method for #with_child and #with_parent
168
+ def handle_parent_child_arguments(other_query, relation, relation_options) # :nodoc:
169
+ return relation, [other_query.match, relation_options]
170
+ end
171
+
172
+ # Filters based on the object's children
173
+ #
174
+ # Matches if this object has at least one child which matches +query+.
175
+ #
176
+ # If +relation+ is given, then only the children in this relation are
177
+ # considered. Moreover, relation options can be used to restrict the
178
+ # search even more.
179
+ #
180
+ # Examples:
181
+ #
182
+ # parent.depends_on(child)
183
+ # TaskMatcher.new.
184
+ # with_child(TaskMatcher.new.pending) === parent # => true
185
+ # TaskMatcher.new.
186
+ # with_child(TaskMatcher.new.pending, Roby::TaskStructure::Dependency) === parent # => true
187
+ # TaskMatcher.new.
188
+ # with_child(TaskMatcher.new.pending, Roby::TaskStructure::PlannedBy) === parent # => false
189
+ #
190
+ # TaskMatcher.new.
191
+ # with_child(TaskMatcher.new.pending,
192
+ # Roby::TaskStructure::Dependency,
193
+ # roles: ["trajectory_following"]) === parent # => false
194
+ # parent.depends_on child, role: "trajectory_following"
195
+ # TaskMatcher.new.
196
+ # with_child(TaskMatcher.new.pending,
197
+ # Roby::TaskStructure::Dependency,
198
+ # roles: ["trajectory_following"]) === parent # => true
199
+ #
200
+ def with_child(other_query, relation = nil, relation_options = nil)
201
+ relation, spec = handle_parent_child_arguments(other_query, relation, relation_options)
202
+ (@children[relation] ||= Array.new) << spec
203
+ @indexed_query = false
204
+ self
205
+ end
206
+
207
+ # Filters based on the object's parents
208
+ #
209
+ # Matches if this object has at least one parent which matches +query+.
210
+ #
211
+ # If +relation+ is given, then only the parents in this relation are
212
+ # considered. Moreover, relation options can be used to restrict the
213
+ # search even more.
214
+ #
215
+ # See examples for #with_child
216
+ def with_parent(other_query, relation = nil, relation_options = nil)
217
+ relation, spec = handle_parent_child_arguments(other_query, relation, relation_options)
218
+ (@parents[relation] ||= Array.new) << spec
219
+ @indexed_query = false
220
+ self
221
+ end
222
+
223
+ # Helper method for handling parent/child matches in #===
224
+ def handle_parent_child_match(object, match_spec) # :nodoc:
225
+ relation, matchers = *match_spec
226
+ return false if !relation && object.relations.empty?
227
+ for match_spec in matchers
228
+ m, relation_options = *match_spec
229
+ if relation
230
+ if !yield(relation, m, relation_options)
231
+ return false
232
+ end
233
+ else
234
+ result = object.relations.any? do |rel|
235
+ yield(rel, m, relation_options)
236
+ end
237
+ return false if !result
238
+ end
239
+ end
240
+ true
241
+ end
242
+
243
+ # Returns true if filtering with this TaskMatcher using #=== is
244
+ # equivalent to calling #filter() using a Index. This is used to
245
+ # avoid an explicit O(N) filtering step after filter() has been called
246
+ def indexed_query?
247
+ @indexed_query
248
+ end
249
+
250
+ def to_s
251
+ description =
252
+ if instance
253
+ instance.to_s
254
+ elsif model.size == 1
255
+ model.first.to_s
256
+ else
257
+ "(#{model.map(&:to_s).join(",")})"
258
+ end
259
+ ([description] + predicates.map(&:to_s) + neg_predicates.map { |p| "not_#{p}" }).join(".")
260
+ end
261
+
262
+
263
+ # Tests whether the given object matches this predicate
264
+ #
265
+ # @param [PlanObject] object the object to match
266
+ # @return [Boolean]
267
+ def ===(object)
268
+ if instance
269
+ return false if object != instance
270
+ end
271
+
272
+ if !model.empty?
273
+ return unless object.fullfills?(model)
274
+ end
275
+
276
+ for parent_spec in @parents
277
+ result = handle_parent_child_match(object, parent_spec) do |relation, m, relation_options|
278
+ object.each_parent_object(relation).
279
+ any? { |parent| m === parent && (!relation_options || relation_options === parent[object, relation]) }
280
+ end
281
+ return false if !result
282
+ end
283
+
284
+ for child_spec in @children
285
+ result = handle_parent_child_match(object, child_spec) do |relation, m, relation_options|
286
+ object.each_child_object(relation).
287
+ any? { |child| m === child && (!relation_options || relation_options === object[child, relation]) }
288
+ end
289
+ return false if !result
290
+ end
291
+
292
+ for pred in predicates
293
+ return false if !object.send(pred)
294
+ end
295
+ for pred in neg_predicates
296
+ return false if object.send(pred)
297
+ end
298
+
299
+ return false if !owners.empty? && !(object.owners - owners).empty?
300
+ true
301
+ end
302
+
303
+ # @api private
304
+ #
305
+ # Resolve the indexed sets needed to filter an initial set in {#filter}
306
+ #
307
+ # @return [(Set,Set)] the positive (intersection) and
308
+ # negative (difference) sets
309
+ def indexed_sets(index)
310
+ positive_sets = []
311
+ for m in @model
312
+ positive_sets << index.by_model[m]
313
+ end
314
+
315
+ for o in @owners
316
+ if candidates = index.by_owner[o]
317
+ positive_sets << candidates
318
+ else
319
+ return [Set.new, Set.new]
320
+ end
321
+ end
322
+
323
+ for pred in @indexed_predicates
324
+ positive_sets << index.by_predicate[pred]
325
+ end
326
+
327
+ negative_sets = @indexed_neg_predicates.
328
+ map { |pred| index.by_predicate[pred] }
329
+
330
+ return positive_sets, negative_sets
331
+ end
332
+
333
+ # Filters the tasks in +initial_set+ by using the information in
334
+ # +index+, and returns the result. The resulting set must
335
+ # include all tasks in +initial_set+ which match with #===, but can
336
+ # include tasks which do not match #===
337
+ #
338
+ # @param [Set] initial_set
339
+ # @param [Index] index
340
+ # @return [Set]
341
+ def filter(initial_set, index, initial_is_complete: false)
342
+ positive_sets, negative_sets = indexed_sets(index)
343
+ positive_sets << initial_set if !initial_is_complete || positive_sets.empty?
344
+
345
+ negative = negative_sets.shift || Set.new
346
+ if negative_sets.size > 1
347
+ negative = negative.dup
348
+ negative_sets.each { |set| negative.merge(set) }
349
+ end
350
+
351
+ positive_sets = positive_sets.sort_by(&:size)
352
+
353
+ result = Set.new
354
+ result.compare_by_identity
355
+ positive_sets.shift.each do |obj|
356
+ result.add(obj) if !negative.include?(obj) && positive_sets.all? { |set| set.include?(obj) }
357
+ end
358
+ return result
359
+ end
360
+ end
361
+ end
362
+ end
363
+