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.
- checksums.yaml +7 -0
- data/.deep-cover.rb +3 -0
- data/.gitattributes +1 -0
- data/.gitignore +24 -0
- data/.simplecov +10 -0
- data/.travis.yml +17 -0
- data/.yardopts +4 -0
- data/Gemfile +15 -0
- data/README.md +11 -0
- data/Rakefile +47 -177
- data/benchmark/{alloc_misc.rb → attic/alloc_misc.rb} +2 -2
- data/benchmark/{discovery_latency.rb → attic/discovery_latency.rb} +19 -19
- data/benchmark/{garbage_collection.rb → attic/garbage_collection.rb} +9 -9
- data/benchmark/{genom.rb → attic/genom.rb} +0 -0
- data/benchmark/attic/transactions.rb +62 -0
- data/benchmark/plan_basic_operations.rb +28 -0
- data/benchmark/relations/graph.rb +63 -0
- data/benchmark/ruby/identity.rb +18 -0
- data/benchmark/ruby/set_intersect_vs_hash_merge.rb +39 -0
- data/benchmark/ruby/yield_vs_block.rb +35 -0
- data/benchmark/run +5 -0
- data/benchmark/synthetic_plan_modifications_with_transactions.rb +79 -0
- data/benchmark/transactions.rb +99 -51
- data/bin/roby +38 -197
- data/bin/roby-display +14 -0
- data/bin/roby-log +3 -176
- data/doc/guide/{src → attic}/abstraction/achieve_with.page +1 -1
- data/doc/guide/{src → attic}/abstraction/forwarding.page +1 -1
- data/doc/guide/{src → attic}/abstraction/hierarchy.page +1 -1
- data/doc/guide/{src → attic}/abstraction/index.page +1 -1
- data/doc/guide/{src → attic}/abstraction/task_models.page +1 -1
- data/doc/guide/{overview.rdoc → attic/cycle/api_overview.rdoc} +6 -1
- data/doc/guide/{src → attic}/cycle/cycle-overview.png +0 -0
- data/doc/guide/{src → attic}/cycle/cycle-overview.svg +0 -0
- data/doc/guide/attic/cycle/error_handling.page +98 -0
- data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.png +0 -0
- data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.svg +0 -0
- data/doc/guide/{src/cycle/error_handling.page → attic/cycle/error_sources.page} +46 -89
- data/doc/guide/{src → attic}/cycle/garbage_collection.page +1 -1
- data/doc/guide/{src → attic}/cycle/index.page +1 -1
- data/doc/guide/{src → attic}/cycle/propagation.page +11 -1
- data/doc/guide/{src → attic}/cycle/propagation_diamond.png +0 -0
- data/doc/guide/{src → attic}/cycle/propagation_diamond.svg +0 -0
- data/doc/guide/attic/plans/building_plans.page +89 -0
- data/doc/guide/attic/plans/code.page +192 -0
- data/doc/guide/{src/basics → attic/plans}/events.page +3 -4
- data/doc/guide/attic/plans/index.page +7 -0
- data/doc/guide/{plan_modifications.rdoc → attic/plans/plan_modifications.rdoc} +5 -3
- data/doc/guide/{src/basics → attic/plans}/plan_objects.page +2 -1
- data/doc/guide/attic/plans/querying_plans.page +5 -0
- data/doc/guide/{src/basics → attic/plans}/tasks.page +20 -20
- data/doc/guide/config.yaml +7 -4
- data/doc/guide/ext/extended_menu.rb +29 -0
- data/doc/guide/ext/init.rb +6 -0
- data/doc/guide/ext/rdoc_links.rb +7 -6
- data/doc/guide/src/advanced_concepts/history.page +5 -0
- data/doc/guide/src/advanced_concepts/index.page +11 -0
- data/doc/guide/src/advanced_concepts/recognizing_patterns.page +83 -0
- data/doc/guide/src/advanced_concepts/scheduling.page +87 -0
- data/doc/guide/src/advanced_concepts/transactions.page +5 -0
- data/doc/guide/src/advanced_concepts/unreachability.page +42 -0
- data/doc/guide/src/base.template +96 -0
- data/doc/guide/src/basics_shell_header.txt +5 -7
- data/doc/guide/src/building/action_coordination.page +96 -0
- data/doc/guide/src/building/actions.page +124 -0
- data/doc/guide/src/building/file_layout.page +71 -0
- data/doc/guide/src/building/index.page +50 -0
- data/doc/guide/src/building/patterns.page +86 -0
- data/doc/guide/src/building/patterns_forwarding.png +0 -0
- data/doc/guide/src/building/patterns_forwarding.svg +277 -0
- data/doc/guide/src/building/runtime.page +95 -0
- data/doc/guide/src/building/task_models.page +94 -0
- data/doc/guide/src/building/tasks.page +284 -0
- data/doc/guide/src/concepts/error_handling.page +100 -0
- data/doc/guide/src/concepts/exception_propagation.png +0 -0
- data/doc/guide/src/concepts/exception_propagation.svg +445 -0
- data/doc/guide/src/concepts/execution.page +85 -0
- data/doc/guide/src/concepts/execution.png +0 -0
- data/doc/guide/src/concepts/execution.svg +573 -0
- data/doc/guide/src/concepts/execution_cycle.png +0 -0
- data/doc/guide/src/concepts/garbage_collection.page +57 -0
- data/doc/guide/src/concepts/index.page +27 -0
- data/doc/guide/src/concepts/plans.page +101 -0
- data/doc/guide/src/concepts/policy.page +31 -0
- data/doc/guide/src/concepts/reactor.page +61 -0
- data/doc/guide/src/concepts/simple_plan_example.png +0 -0
- data/doc/guide/src/concepts/simple_plan_example.svg +376 -0
- data/doc/guide/src/default.template +9 -74
- data/doc/guide/src/event_relations/forward.page +71 -0
- data/doc/guide/src/event_relations/index.page +12 -0
- data/doc/guide/src/event_relations/scheduling_constraints.page +43 -0
- data/doc/guide/src/event_relations/signal.page +55 -0
- data/doc/guide/src/event_relations/temporal_constraints.page +77 -0
- data/doc/guide/src/htmldoc.metainfo +21 -8
- data/doc/guide/src/index.page +8 -3
- data/doc/guide/src/{introduction/install.page → installation/index.page} +37 -25
- data/doc/guide/src/installation/publications.page +14 -0
- data/doc/guide/src/{introduction → installation}/videos.page +14 -7
- data/doc/guide/src/interacting/index.page +16 -0
- data/doc/guide/src/interacting/run.page +33 -0
- data/doc/guide/src/interacting/shell.page +95 -0
- data/doc/guide/src/plugins/creating_plugins.page +72 -0
- data/doc/guide/src/plugins/index.page +27 -5
- data/doc/guide/src/plugins/{fault_tolerance.page → standard_plugins/fault_tolerance.page} +2 -2
- data/doc/guide/src/plugins/standard_plugins/index.page +11 -0
- data/doc/guide/src/plugins/{subsystems.page → standard_plugins/subsystems.page} +2 -2
- data/doc/guide/src/style_screen.css +687 -0
- data/doc/guide/src/task_relations/dependency.page +107 -0
- data/doc/guide/src/task_relations/executed_by.page +77 -0
- data/doc/guide/src/task_relations/index.page +12 -0
- data/doc/guide/src/task_relations/new_relations.page +119 -0
- data/doc/guide/src/task_relations/planned_by.page +46 -0
- data/doc/guide/src/tutorial/app.page +117 -0
- data/doc/guide/src/{basics → tutorial}/code_examples.page +6 -5
- data/doc/guide/src/{basics → tutorial}/dry.page +15 -15
- data/doc/guide/src/{basics → tutorial}/errors.page +43 -68
- data/doc/guide/src/tutorial/events.page +195 -0
- data/doc/guide/src/{basics → tutorial}/hierarchy.page +53 -52
- data/doc/guide/src/tutorial/index.page +13 -0
- data/doc/guide/src/tutorial/log_replay/goForward_1.png +0 -0
- data/doc/guide/src/tutorial/log_replay/goForward_2.png +0 -0
- data/doc/guide/src/tutorial/log_replay/goForward_3.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/goForward_4.png +0 -0
- data/doc/guide/src/tutorial/log_replay/goForward_5.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_1.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_2.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_3.png +0 -0
- data/doc/guide/src/tutorial/log_replay/moveto_code_error.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_1.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_2.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_3.png +0 -0
- data/doc/guide/src/tutorial/log_replay/plan_repair_4.png +0 -0
- data/doc/guide/src/tutorial/log_replay/roby_log_main_window.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/roby_log_relation_window.png +0 -0
- data/doc/guide/src/{basics → tutorial}/log_replay/roby_replay_event_representation.png +0 -0
- data/doc/guide/src/tutorial/relations_display.page +153 -0
- data/doc/guide/src/{basics → tutorial}/roby_cycle_overview.png +0 -0
- data/doc/guide/src/tutorial/shell.page +121 -0
- data/doc/guide/src/{basics → tutorial}/summary.page +1 -1
- data/doc/guide/src/tutorial/tasks.page +374 -0
- data/lib/roby.rb +102 -47
- data/lib/roby/actions.rb +17 -0
- data/lib/roby/actions/action.rb +80 -0
- data/lib/roby/actions/interface.rb +45 -0
- data/lib/roby/actions/library.rb +23 -0
- data/lib/roby/actions/models/action.rb +224 -0
- data/lib/roby/actions/models/coordination_action.rb +58 -0
- data/lib/roby/actions/models/interface.rb +22 -0
- data/lib/roby/actions/models/interface_base.rb +294 -0
- data/lib/roby/actions/models/library.rb +12 -0
- data/lib/roby/actions/models/method_action.rb +90 -0
- data/lib/roby/actions/task.rb +114 -0
- data/lib/roby/and_generator.rb +125 -0
- data/lib/roby/app.rb +2795 -829
- data/lib/roby/app/autotest_console_reporter.rb +138 -0
- data/lib/roby/app/base.rb +21 -0
- data/lib/roby/app/cucumber.rb +2 -0
- data/lib/roby/app/cucumber/controller.rb +439 -0
- data/lib/roby/app/cucumber/helpers.rb +280 -0
- data/lib/roby/app/cucumber/world.rb +32 -0
- data/lib/roby/app/debug.rb +136 -0
- data/lib/roby/app/gen.rb +2 -0
- data/lib/roby/app/rake.rb +178 -38
- data/lib/roby/app/robot_config.rb +9 -0
- data/lib/roby/app/robot_names.rb +115 -0
- data/lib/roby/app/run.rb +3 -2
- data/lib/roby/app/scripts.rb +72 -0
- data/lib/roby/app/scripts/autotest.rb +173 -0
- data/lib/roby/app/scripts/display.rb +2 -0
- data/lib/roby/app/scripts/restart.rb +52 -0
- data/lib/roby/app/scripts/results.rb +17 -8
- data/lib/roby/app/scripts/run.rb +155 -24
- data/lib/roby/app/scripts/shell.rb +147 -62
- data/lib/roby/app/scripts/test.rb +107 -22
- data/lib/roby/app/test_reporter.rb +74 -0
- data/lib/roby/app/test_server.rb +159 -0
- data/lib/roby/app/vagrant.rb +47 -0
- data/lib/roby/backports.rb +16 -0
- data/lib/roby/cli/display.rb +190 -0
- data/lib/roby/cli/exceptions.rb +17 -0
- data/lib/roby/cli/gen/actions/class.rb +5 -0
- data/lib/roby/cli/gen/actions/test.rb +6 -0
- data/lib/roby/cli/gen/app/.yardopts +6 -0
- data/lib/roby/cli/gen/app/README.md +28 -0
- data/lib/roby/cli/gen/app/Rakefile +15 -0
- data/{app → lib/roby/cli/gen/app}/config/app.yml +29 -39
- data/lib/roby/cli/gen/app/models/.gitattributes +1 -0
- data/{app → lib/roby/cli/gen/app/scripts}/controllers/.gitattributes +0 -0
- data/{app/data/.gitattributes → lib/roby/cli/gen/app/test/.gitignore} +0 -0
- data/lib/roby/cli/gen/class/class.rb +6 -0
- data/lib/roby/cli/gen/class/test.rb +7 -0
- data/lib/roby/cli/gen/helpers.rb +203 -0
- data/lib/roby/cli/gen/module/module.rb +5 -0
- data/lib/roby/cli/gen/module/test.rb +6 -0
- data/lib/roby/cli/gen/roby_app/config/init.rb +17 -0
- data/lib/roby/cli/gen/roby_app/config/robots/robot.rb +40 -0
- data/lib/roby/cli/gen/task/class.rb +44 -0
- data/lib/roby/cli/gen/task/test.rb +6 -0
- data/lib/roby/cli/gen_main.rb +120 -0
- data/lib/roby/cli/log.rb +276 -0
- data/lib/roby/cli/log/flamegraph.html +499 -0
- data/lib/roby/cli/log/flamegraph_renderer.rb +88 -0
- data/lib/roby/cli/main.rb +153 -0
- data/lib/roby/coordination.rb +60 -0
- data/lib/roby/coordination/action_script.rb +25 -0
- data/lib/roby/coordination/action_state_machine.rb +125 -0
- data/lib/roby/coordination/actions.rb +106 -0
- data/lib/roby/coordination/base.rb +145 -0
- data/lib/roby/coordination/calculus.rb +40 -0
- data/lib/roby/coordination/child.rb +28 -0
- data/lib/roby/coordination/event.rb +29 -0
- data/lib/roby/coordination/fault_handler.rb +25 -0
- data/lib/roby/coordination/fault_handling_task.rb +13 -0
- data/lib/roby/coordination/fault_response_table.rb +110 -0
- data/lib/roby/coordination/models/action_script.rb +64 -0
- data/lib/roby/coordination/models/action_state_machine.rb +224 -0
- data/lib/roby/coordination/models/actions.rb +191 -0
- data/lib/roby/coordination/models/arguments.rb +55 -0
- data/lib/roby/coordination/models/base.rb +176 -0
- data/lib/roby/coordination/models/capture.rb +86 -0
- data/lib/roby/coordination/models/child.rb +35 -0
- data/lib/roby/coordination/models/event.rb +41 -0
- data/lib/roby/coordination/models/exceptions.rb +42 -0
- data/lib/roby/coordination/models/fault_handler.rb +219 -0
- data/lib/roby/coordination/models/fault_response_table.rb +77 -0
- data/lib/roby/coordination/models/root.rb +22 -0
- data/lib/roby/coordination/models/script.rb +283 -0
- data/lib/roby/coordination/models/task.rb +184 -0
- data/lib/roby/coordination/models/task_from_action.rb +50 -0
- data/lib/roby/coordination/models/task_from_as_plan.rb +33 -0
- data/lib/roby/coordination/models/task_from_instanciation_object.rb +31 -0
- data/lib/roby/coordination/models/task_from_variable.rb +27 -0
- data/lib/roby/coordination/models/task_with_dependencies.rb +48 -0
- data/lib/roby/coordination/models/variable.rb +32 -0
- data/lib/roby/coordination/script.rb +200 -0
- data/lib/roby/coordination/script_instruction.rb +12 -0
- data/lib/roby/coordination/task.rb +45 -0
- data/lib/roby/coordination/task_base.rb +69 -0
- data/lib/roby/coordination/task_script.rb +293 -0
- data/lib/roby/coordination/task_state_machine.rb +308 -0
- data/lib/roby/decision_control.rb +33 -21
- data/lib/roby/distributed_object.rb +76 -0
- data/lib/roby/droby.rb +17 -0
- data/lib/roby/droby/droby_id.rb +6 -0
- data/lib/roby/droby/enable.rb +153 -0
- data/lib/roby/droby/event_logger.rb +189 -0
- data/lib/roby/droby/event_logging.rb +57 -0
- data/lib/roby/droby/exceptions.rb +14 -0
- data/lib/roby/droby/identifiable.rb +22 -0
- data/lib/roby/droby/logfile.rb +141 -0
- data/lib/roby/droby/logfile/client.rb +176 -0
- data/lib/roby/droby/logfile/file_format.md +97 -0
- data/lib/roby/droby/logfile/index.rb +117 -0
- data/lib/roby/droby/logfile/reader.rb +139 -0
- data/lib/roby/droby/logfile/server.rb +199 -0
- data/lib/roby/droby/logfile/writer.rb +114 -0
- data/lib/roby/droby/marshal.rb +264 -0
- data/lib/roby/droby/marshallable.rb +12 -0
- data/lib/roby/droby/null_event_logger.rb +25 -0
- data/lib/roby/droby/object_manager.rb +205 -0
- data/lib/roby/droby/peer_id.rb +6 -0
- data/lib/roby/droby/plan_rebuilder.rb +373 -0
- data/lib/roby/droby/rebuilt_plan.rb +160 -0
- data/lib/roby/droby/remote_droby_id.rb +6 -0
- data/lib/roby/droby/timepoints.rb +205 -0
- data/lib/roby/droby/timepoints_ctf.metadata.erb +101 -0
- data/lib/roby/droby/timepoints_ctf.rb +125 -0
- data/lib/roby/droby/v5.rb +14 -0
- data/lib/roby/droby/v5/builtin.rb +120 -0
- data/lib/roby/droby/v5/droby_class.rb +45 -0
- data/lib/roby/droby/v5/droby_constant.rb +81 -0
- data/lib/roby/droby/v5/droby_dump.rb +1026 -0
- data/lib/roby/droby/v5/droby_id.rb +44 -0
- data/lib/roby/droby/v5/droby_model.rb +82 -0
- data/lib/roby/droby/v5/peer_id.rb +10 -0
- data/lib/roby/droby/v5/remote_droby_id.rb +42 -0
- data/lib/roby/event.rb +79 -957
- data/lib/roby/event_constraints.rb +835 -0
- data/lib/roby/event_generator.rb +1047 -0
- data/lib/roby/event_structure/causal_link.rb +6 -0
- data/lib/roby/event_structure/forwarding.rb +6 -0
- data/lib/roby/event_structure/precedence.rb +7 -0
- data/lib/roby/event_structure/signal.rb +8 -0
- data/lib/roby/event_structure/temporal_constraints.rb +640 -0
- data/lib/roby/exceptions.rb +446 -152
- data/lib/roby/executable_plan.rb +549 -0
- data/lib/roby/execution_engine.rb +1997 -950
- data/lib/roby/filter_generator.rb +26 -0
- data/lib/roby/gui/chronicle_view.rb +225 -0
- data/lib/roby/gui/chronicle_widget.rb +925 -0
- data/lib/roby/gui/dot_id.rb +11 -0
- data/lib/roby/gui/exception_view.rb +44 -0
- data/lib/roby/gui/log_display.rb +273 -0
- data/lib/roby/gui/model_views.rb +2 -0
- data/lib/roby/gui/model_views/action_interface.rb +53 -0
- data/lib/roby/gui/model_views/task.rb +47 -0
- data/lib/roby/gui/model_views/task.rhtml +41 -0
- data/lib/roby/gui/object_info_view.rb +89 -0
- data/lib/roby/gui/plan_dot_layout.rb +427 -0
- data/lib/roby/gui/plan_rebuilder_widget.rb +357 -0
- data/lib/roby/gui/qt4_toMSecsSinceEpoch.rb +8 -0
- data/lib/roby/gui/relations_view.rb +278 -0
- data/lib/roby/gui/relations_view/relations.ui +139 -0
- data/lib/roby/gui/relations_view/relations_canvas.rb +1088 -0
- data/lib/roby/gui/relations_view/relations_config.rb +292 -0
- data/lib/roby/gui/relations_view/relations_view.ui +53 -0
- data/lib/roby/gui/scheduler_view.css +24 -0
- data/lib/roby/gui/scheduler_view.rb +46 -0
- data/lib/roby/gui/scheduler_view.rhtml +53 -0
- data/lib/roby/gui/stepping.rb +93 -0
- data/lib/roby/gui/stepping.ui +181 -0
- data/lib/roby/gui/styles.rb +81 -0
- data/lib/roby/gui/task_display_configuration.rb +42 -0
- data/lib/roby/gui/task_state_at.rb +38 -0
- data/lib/roby/hooks.rb +26 -0
- data/lib/roby/interface.rb +136 -469
- data/lib/roby/interface/async.rb +20 -0
- data/lib/roby/interface/async/action_monitor.rb +188 -0
- data/lib/roby/interface/async/interface.rb +498 -0
- data/lib/roby/interface/async/job_monitor.rb +213 -0
- data/lib/roby/interface/async/log.rb +238 -0
- data/lib/roby/interface/async/new_job_listener.rb +79 -0
- data/lib/roby/interface/async/ui_connector.rb +183 -0
- data/lib/roby/interface/client.rb +553 -0
- data/lib/roby/interface/command.rb +24 -0
- data/lib/roby/interface/command_argument.rb +16 -0
- data/lib/roby/interface/command_library.rb +92 -0
- data/lib/roby/interface/droby_channel.rb +174 -0
- data/lib/roby/interface/exceptions.rb +22 -0
- data/lib/roby/interface/interface.rb +655 -0
- data/lib/roby/interface/job.rb +47 -0
- data/lib/roby/interface/rest.rb +10 -0
- data/lib/roby/interface/rest/api.rb +29 -0
- data/lib/roby/interface/rest/helpers.rb +24 -0
- data/lib/roby/interface/rest/server.rb +212 -0
- data/lib/roby/interface/server.rb +154 -0
- data/lib/roby/interface/shell_client.rb +468 -0
- data/lib/roby/interface/shell_subcommand.rb +24 -0
- data/lib/roby/interface/subcommand_client.rb +35 -0
- data/lib/roby/interface/tcp.rb +168 -0
- data/lib/roby/models/arguments.rb +112 -0
- data/lib/roby/models/plan_object.rb +83 -0
- data/lib/roby/models/task.rb +835 -0
- data/lib/roby/models/task_event.rb +62 -0
- data/lib/roby/models/task_service.rb +78 -0
- data/lib/roby/or_generator.rb +88 -0
- data/lib/roby/plan.rb +1751 -864
- data/lib/roby/plan_object.rb +611 -0
- data/lib/roby/plan_service.rb +200 -0
- data/lib/roby/promise.rb +332 -0
- data/lib/roby/queries.rb +23 -0
- data/lib/roby/queries/and_matcher.rb +32 -0
- data/lib/roby/queries/any.rb +27 -0
- data/lib/roby/queries/code_error_matcher.rb +58 -0
- data/lib/roby/queries/event_generator_matcher.rb +9 -0
- data/lib/roby/queries/execution_exception_matcher.rb +165 -0
- data/lib/roby/queries/index.rb +165 -0
- data/lib/roby/queries/localized_error_matcher.rb +149 -0
- data/lib/roby/queries/matcher_base.rb +107 -0
- data/lib/roby/queries/none.rb +27 -0
- data/lib/roby/queries/not_matcher.rb +30 -0
- data/lib/roby/queries/op_matcher.rb +8 -0
- data/lib/roby/queries/or_matcher.rb +30 -0
- data/lib/roby/queries/plan_object_matcher.rb +363 -0
- data/lib/roby/queries/query.rb +188 -0
- data/lib/roby/queries/task_event_generator_matcher.rb +86 -0
- data/lib/roby/queries/task_matcher.rb +344 -0
- data/lib/roby/relations.rb +42 -678
- data/lib/roby/relations/bidirectional_directed_adjacency_graph.rb +492 -0
- data/lib/roby/relations/directed_relation_support.rb +268 -0
- data/lib/roby/relations/event_relation_graph.rb +19 -0
- data/lib/roby/relations/fork_merge_visitor.rb +154 -0
- data/lib/roby/relations/graph.rb +533 -0
- data/lib/roby/relations/models/directed_relation_support.rb +11 -0
- data/lib/roby/relations/models/graph.rb +75 -0
- data/lib/roby/relations/models/task_relation_graph.rb +18 -0
- data/lib/roby/relations/space.rb +380 -0
- data/lib/roby/relations/task_relation_graph.rb +20 -0
- data/lib/roby/robot.rb +85 -38
- data/lib/roby/schedulers/basic.rb +155 -25
- data/lib/roby/schedulers/null.rb +20 -0
- data/lib/roby/schedulers/reporting.rb +31 -0
- data/lib/roby/schedulers/state.rb +129 -0
- data/lib/roby/schedulers/temporal.rb +91 -0
- data/lib/roby/singletons.rb +87 -0
- data/lib/roby/standalone.rb +4 -2
- data/lib/roby/standard_errors.rb +405 -82
- data/lib/roby/state.rb +6 -3
- data/lib/roby/state/conf_model.rb +5 -0
- data/lib/roby/state/events.rb +181 -95
- data/lib/roby/state/goal_model.rb +77 -0
- data/lib/roby/state/open_struct.rb +591 -0
- data/lib/roby/state/open_struct_model.rb +68 -0
- data/lib/roby/state/pos.rb +45 -45
- data/lib/roby/state/shapes.rb +11 -11
- data/lib/roby/state/state_model.rb +303 -0
- data/lib/roby/state/task.rb +43 -0
- data/lib/roby/support.rb +88 -148
- data/lib/roby/task.rb +1361 -1750
- data/lib/roby/task_arguments.rb +428 -0
- data/lib/roby/task_event.rb +127 -0
- data/lib/roby/task_event_generator.rb +337 -0
- data/lib/roby/task_service.rb +6 -0
- data/lib/roby/task_structure/conflicts.rb +104 -0
- data/lib/roby/task_structure/dependency.rb +932 -0
- data/lib/roby/task_structure/error_handling.rb +118 -0
- data/lib/roby/task_structure/executed_by.rb +234 -0
- data/lib/roby/task_structure/planned_by.rb +90 -0
- data/lib/roby/tasks/aggregator.rb +37 -0
- data/lib/roby/tasks/external_process.rb +275 -0
- data/lib/roby/tasks/group.rb +27 -0
- data/lib/roby/tasks/null.rb +19 -0
- data/lib/roby/tasks/parallel.rb +43 -0
- data/lib/roby/tasks/sequence.rb +88 -0
- data/lib/roby/tasks/simple.rb +21 -0
- data/lib/roby/{thread_task.rb → tasks/thread.rb} +50 -24
- data/lib/roby/tasks/timeout.rb +17 -0
- data/lib/roby/tasks/virtual.rb +55 -0
- data/lib/roby/template_plan.rb +7 -0
- data/lib/roby/test/aruba_minitest.rb +74 -0
- data/lib/roby/test/assertion.rb +16 -0
- data/lib/roby/test/assertions.rb +490 -0
- data/lib/roby/test/common.rb +368 -591
- data/lib/roby/test/dsl.rb +149 -0
- data/lib/roby/test/error.rb +18 -0
- data/lib/roby/test/event_reporter.rb +83 -0
- data/lib/roby/test/execution_expectations.rb +1134 -0
- data/lib/roby/test/expect_execution.rb +151 -0
- data/lib/roby/test/minitest_helpers.rb +166 -0
- data/lib/roby/test/roby_app_helpers.rb +200 -0
- data/lib/roby/test/run_planners.rb +155 -0
- data/lib/roby/test/self.rb +112 -0
- data/lib/roby/test/spec.rb +198 -0
- data/lib/roby/test/tasks/empty_task.rb +4 -4
- data/lib/roby/test/tasks/goto.rb +28 -27
- data/lib/roby/test/teardown_plans.rb +100 -0
- data/lib/roby/test/testcase.rb +239 -307
- data/lib/roby/test/tools.rb +159 -155
- data/lib/roby/test/validate_state_machine.rb +75 -0
- data/lib/roby/transaction.rb +1125 -0
- data/lib/roby/transaction/event_generator_proxy.rb +63 -0
- data/lib/roby/transaction/plan_object_proxy.rb +99 -0
- data/lib/roby/transaction/plan_service_proxy.rb +43 -0
- data/lib/roby/transaction/proxying.rb +120 -0
- data/lib/roby/transaction/task_event_generator_proxy.rb +19 -0
- data/lib/roby/transaction/task_proxy.rb +135 -0
- data/lib/roby/until_generator.rb +30 -0
- data/lib/roby/version.rb +5 -0
- data/lib/roby/yard.rb +169 -0
- data/lib/yard-roby.rb +1 -0
- data/manifest.xml +32 -6
- data/roby.gemspec +59 -0
- metadata +788 -587
- data/Manifest.txt +0 -321
- data/NOTES +0 -4
- data/README.txt +0 -166
- data/TODO.txt +0 -146
- data/app/README.txt +0 -24
- data/app/Rakefile +0 -8
- data/app/config/ROBOT.rb +0 -5
- data/app/config/init.rb +0 -33
- data/app/config/roby.yml +0 -3
- data/app/controllers/ROBOT.rb +0 -2
- data/app/planners/ROBOT/main.rb +0 -6
- data/app/planners/main.rb +0 -5
- data/app/scripts/distributed +0 -3
- data/app/scripts/generate/bookmarks +0 -3
- data/app/scripts/replay +0 -3
- data/app/scripts/results +0 -3
- data/app/scripts/run +0 -3
- data/app/scripts/server +0 -3
- data/app/scripts/shell +0 -3
- data/app/scripts/test +0 -3
- data/app/tasks/.gitattributes +0 -0
- data/app/tasks/ROBOT/.gitattributes +0 -0
- data/bin/roby-shell +0 -25
- data/doc/guide/src/basics/app.page +0 -139
- data/doc/guide/src/basics/index.page +0 -11
- data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
- data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
- data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
- data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
- data/doc/guide/src/basics/relations_display.page +0 -203
- data/doc/guide/src/basics/shell.page +0 -102
- data/doc/guide/src/default.css +0 -319
- data/doc/guide/src/introduction/index.page +0 -29
- data/doc/guide/src/introduction/publications.page +0 -14
- data/doc/guide/src/relations/dependency.page +0 -89
- data/doc/guide/src/relations/index.page +0 -12
- data/ext/droby/dump.cc +0 -175
- data/ext/droby/extconf.rb +0 -3
- data/ext/graph/algorithm.cc +0 -746
- data/ext/graph/extconf.rb +0 -7
- data/ext/graph/graph.cc +0 -575
- data/ext/graph/graph.hh +0 -183
- data/ext/graph/iterator_sequence.hh +0 -102
- data/ext/graph/undirected_dfs.hh +0 -226
- data/ext/graph/undirected_graph.hh +0 -421
- data/lib/roby/app/scripts/generate/bookmarks.rb +0 -162
- data/lib/roby/app/scripts/replay.rb +0 -31
- data/lib/roby/app/scripts/server.rb +0 -18
- data/lib/roby/basic_object.rb +0 -151
- data/lib/roby/config.rb +0 -14
- data/lib/roby/distributed.rb +0 -36
- data/lib/roby/distributed/base.rb +0 -448
- data/lib/roby/distributed/communication.rb +0 -875
- data/lib/roby/distributed/connection_space.rb +0 -616
- data/lib/roby/distributed/distributed_object.rb +0 -206
- data/lib/roby/distributed/drb.rb +0 -62
- data/lib/roby/distributed/notifications.rb +0 -531
- data/lib/roby/distributed/peer.rb +0 -555
- data/lib/roby/distributed/protocol.rb +0 -529
- data/lib/roby/distributed/proxy.rb +0 -343
- data/lib/roby/distributed/subscription.rb +0 -311
- data/lib/roby/distributed/transaction.rb +0 -498
- data/lib/roby/external_process_task.rb +0 -225
- data/lib/roby/graph.rb +0 -160
- data/lib/roby/log.rb +0 -3
- data/lib/roby/log/chronicle.rb +0 -303
- data/lib/roby/log/console.rb +0 -74
- data/lib/roby/log/data_stream.rb +0 -275
- data/lib/roby/log/dot.rb +0 -279
- data/lib/roby/log/event_stream.rb +0 -161
- data/lib/roby/log/file.rb +0 -396
- data/lib/roby/log/gui/basic_display.ui +0 -83
- data/lib/roby/log/gui/basic_display_ui.rb +0 -89
- data/lib/roby/log/gui/chronicle.rb +0 -26
- data/lib/roby/log/gui/chronicle_view.rb +0 -40
- data/lib/roby/log/gui/chronicle_view.ui +0 -70
- data/lib/roby/log/gui/chronicle_view_ui.rb +0 -90
- data/lib/roby/log/gui/data_displays.rb +0 -171
- data/lib/roby/log/gui/data_displays.ui +0 -155
- data/lib/roby/log/gui/data_displays_ui.rb +0 -146
- data/lib/roby/log/gui/notifications.rb +0 -26
- data/lib/roby/log/gui/relations.rb +0 -269
- data/lib/roby/log/gui/relations.ui +0 -123
- data/lib/roby/log/gui/relations_ui.rb +0 -120
- data/lib/roby/log/gui/relations_view.rb +0 -185
- data/lib/roby/log/gui/relations_view.ui +0 -149
- data/lib/roby/log/gui/relations_view_ui.rb +0 -144
- data/lib/roby/log/gui/replay.rb +0 -366
- data/lib/roby/log/gui/replay_controls.rb +0 -206
- data/lib/roby/log/gui/replay_controls.ui +0 -282
- data/lib/roby/log/gui/replay_controls_ui.rb +0 -249
- data/lib/roby/log/gui/runtime.rb +0 -130
- data/lib/roby/log/hooks.rb +0 -186
- data/lib/roby/log/logger.rb +0 -203
- data/lib/roby/log/notifications.rb +0 -244
- data/lib/roby/log/plan_rebuilder.rb +0 -468
- data/lib/roby/log/relations.rb +0 -1084
- data/lib/roby/log/server.rb +0 -547
- data/lib/roby/log/sqlite.rb +0 -47
- data/lib/roby/log/timings.rb +0 -233
- data/lib/roby/plan-object.rb +0 -371
- data/lib/roby/planning.rb +0 -13
- data/lib/roby/planning/loops.rb +0 -309
- data/lib/roby/planning/model.rb +0 -1012
- data/lib/roby/planning/task.rb +0 -180
- data/lib/roby/query.rb +0 -655
- data/lib/roby/relations/conflicts.rb +0 -67
- data/lib/roby/relations/dependency.rb +0 -358
- data/lib/roby/relations/ensured.rb +0 -19
- data/lib/roby/relations/error_handling.rb +0 -22
- data/lib/roby/relations/events.rb +0 -7
- data/lib/roby/relations/executed_by.rb +0 -208
- data/lib/roby/relations/influence.rb +0 -10
- data/lib/roby/relations/planned_by.rb +0 -63
- data/lib/roby/state/information.rb +0 -55
- data/lib/roby/state/state.rb +0 -367
- data/lib/roby/task-operations.rb +0 -186
- data/lib/roby/task_index.rb +0 -80
- data/lib/roby/test/distributed.rb +0 -230
- data/lib/roby/test/tasks/simple_task.rb +0 -23
- data/lib/roby/transactions.rb +0 -507
- data/lib/roby/transactions/proxy.rb +0 -325
- data/plugins/fault_injection/History.txt +0 -4
- data/plugins/fault_injection/README.txt +0 -34
- data/plugins/fault_injection/Rakefile +0 -12
- data/plugins/fault_injection/TODO.txt +0 -0
- data/plugins/fault_injection/app.rb +0 -52
- data/plugins/fault_injection/fault_injection.rb +0 -89
- data/plugins/fault_injection/test/test_fault_injection.rb +0 -78
- data/plugins/subsystems/README.txt +0 -37
- data/plugins/subsystems/Rakefile +0 -13
- data/plugins/subsystems/app.rb +0 -182
- data/plugins/subsystems/test/app/README +0 -24
- data/plugins/subsystems/test/app/Rakefile +0 -8
- data/plugins/subsystems/test/app/config/app.yml +0 -71
- data/plugins/subsystems/test/app/config/init.rb +0 -12
- data/plugins/subsystems/test/app/config/roby.yml +0 -3
- data/plugins/subsystems/test/app/planners/main.rb +0 -20
- data/plugins/subsystems/test/app/scripts/distributed +0 -3
- data/plugins/subsystems/test/app/scripts/replay +0 -3
- data/plugins/subsystems/test/app/scripts/results +0 -3
- data/plugins/subsystems/test/app/scripts/run +0 -3
- data/plugins/subsystems/test/app/scripts/server +0 -3
- data/plugins/subsystems/test/app/scripts/shell +0 -3
- data/plugins/subsystems/test/app/scripts/test +0 -3
- data/plugins/subsystems/test/app/tasks/services.rb +0 -15
- data/plugins/subsystems/test/test_subsystems.rb +0 -78
- data/test/distributed/test_communication.rb +0 -195
- data/test/distributed/test_connection.rb +0 -284
- data/test/distributed/test_execution.rb +0 -378
- data/test/distributed/test_mixed_plan.rb +0 -341
- data/test/distributed/test_plan_notifications.rb +0 -238
- data/test/distributed/test_protocol.rb +0 -525
- data/test/distributed/test_query.rb +0 -106
- data/test/distributed/test_remote_plan.rb +0 -491
- data/test/distributed/test_transaction.rb +0 -466
- data/test/mockups/external_process +0 -28
- data/test/mockups/tasks.rb +0 -27
- data/test/planning/test_loops.rb +0 -432
- data/test/planning/test_model.rb +0 -427
- data/test/planning/test_task.rb +0 -126
- data/test/relations/test_conflicts.rb +0 -42
- data/test/relations/test_dependency.rb +0 -324
- data/test/relations/test_ensured.rb +0 -38
- data/test/relations/test_executed_by.rb +0 -224
- data/test/relations/test_planned_by.rb +0 -56
- data/test/suite_core.rb +0 -29
- data/test/suite_distributed.rb +0 -10
- data/test/suite_planning.rb +0 -4
- data/test/suite_relations.rb +0 -8
- data/test/tasks/test_external_process.rb +0 -126
- data/test/tasks/test_thread_task.rb +0 -70
- data/test/test_bgl.rb +0 -528
- data/test/test_event.rb +0 -969
- data/test/test_exceptions.rb +0 -591
- data/test/test_execution_engine.rb +0 -987
- data/test/test_gui.rb +0 -20
- data/test/test_interface.rb +0 -43
- data/test/test_log.rb +0 -125
- data/test/test_log_server.rb +0 -133
- data/test/test_plan.rb +0 -418
- data/test/test_query.rb +0 -424
- data/test/test_relations.rb +0 -260
- data/test/test_state.rb +0 -432
- data/test/test_support.rb +0 -16
- data/test/test_task.rb +0 -1181
- data/test/test_testcase.rb +0 -138
- data/test/test_transactions.rb +0 -610
- data/test/test_transactions_proxy.rb +0 -216
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
module Roby
|
|
2
|
+
module App
|
|
3
|
+
# Reporter class for the Roby autotest, that outputs on an IO object
|
|
4
|
+
class AutotestConsoleReporter
|
|
5
|
+
# @return [#puts] the IO on which reporting should be done
|
|
6
|
+
attr_reader :io
|
|
7
|
+
|
|
8
|
+
# @return [App::TestServer] the test server
|
|
9
|
+
attr_reader :server
|
|
10
|
+
|
|
11
|
+
# @return [Autorespawn::Manager] the autorespawn slave manager
|
|
12
|
+
attr_reader :manager
|
|
13
|
+
|
|
14
|
+
# @return [Hash<Autorespawn::Slave,Integer>] mapping from
|
|
15
|
+
# a slave to the unique ID associated with it
|
|
16
|
+
attr_reader :slave_to_id
|
|
17
|
+
|
|
18
|
+
# @return [Hash<Integer,Autorespawn::Slave>] mapping from
|
|
19
|
+
# a process ID to the slave object
|
|
20
|
+
attr_reader :pid_to_slave
|
|
21
|
+
|
|
22
|
+
# @api private
|
|
23
|
+
#
|
|
24
|
+
# Converts a slave object to the string displayed to the user
|
|
25
|
+
def slave_to_s(slave)
|
|
26
|
+
slave.name.sort_by(&:first).map { |k, v| "#{k}: #{v}" }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @api private
|
|
30
|
+
#
|
|
31
|
+
# Register a new slave
|
|
32
|
+
#
|
|
33
|
+
# @return [Integer] the unique slave ID
|
|
34
|
+
def register_slave(slave)
|
|
35
|
+
if slave_to_id[slave]
|
|
36
|
+
raise ArgumentError, "#{slave} is already registered"
|
|
37
|
+
end
|
|
38
|
+
slave_to_id[slave] = (@slave_id += 1)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @api private
|
|
42
|
+
#
|
|
43
|
+
# Register a new slave-to-PID mapping
|
|
44
|
+
#
|
|
45
|
+
# @param [Autorespawn::Slave] slave a slave whose #pid is valid
|
|
46
|
+
# @return [Integer] the slave's unique slave ID
|
|
47
|
+
# @raise [ArgumentError] if the slave has not been registered with
|
|
48
|
+
# {#register_slave} first
|
|
49
|
+
def register_slave_pid(slave)
|
|
50
|
+
if slave_id = slave_to_id[slave]
|
|
51
|
+
pid_to_slave[slave.pid] = slave
|
|
52
|
+
return slave_id
|
|
53
|
+
else
|
|
54
|
+
raise ArgumentError, "#{slave} has not been registered with #register_slave"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @api private
|
|
59
|
+
#
|
|
60
|
+
# Returns a slave from its PID
|
|
61
|
+
#
|
|
62
|
+
# @param [Integer] pid the PID
|
|
63
|
+
# @return [(Autorespawn::Slave,Integer)] the slave and its unique
|
|
64
|
+
# slave ID
|
|
65
|
+
# @raise [ArgumentError] if no slave is registered for this PID
|
|
66
|
+
def slave_from_pid(pid)
|
|
67
|
+
if slave = pid_to_slave[pid]
|
|
68
|
+
return slave, slave_to_id[slave]
|
|
69
|
+
else
|
|
70
|
+
raise ArgumentError, "no slave registered for PID #{pid}"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @api private
|
|
75
|
+
#
|
|
76
|
+
# Deregisters a slave-to-PID mapping
|
|
77
|
+
#
|
|
78
|
+
# @return [(Autorespawn::Slave,Integer)] the slave object and unique
|
|
79
|
+
# slave ID that were associated with the slave
|
|
80
|
+
# @raise [ArgumentError] if there is no slave associated with the
|
|
81
|
+
# PID
|
|
82
|
+
def deregister_slave_pid(pid)
|
|
83
|
+
if slave = pid_to_slave.delete(pid)
|
|
84
|
+
return slave, slave_to_id[slave]
|
|
85
|
+
else
|
|
86
|
+
raise ArgumentError, "no slave known for #{pid}"
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def initialize(server, manager, io: STDOUT)
|
|
91
|
+
@io = io
|
|
92
|
+
@slave_id = 0
|
|
93
|
+
@slave_to_id = Hash.new
|
|
94
|
+
@pid_to_slave = Hash.new
|
|
95
|
+
manager.on_slave_new do |slave|
|
|
96
|
+
slave_id = register_slave(slave)
|
|
97
|
+
io.puts "[##{slave_id}] new slave #{slave_to_s(slave)}"
|
|
98
|
+
end
|
|
99
|
+
manager.on_slave_start do |slave|
|
|
100
|
+
slave_id = register_slave_pid(slave)
|
|
101
|
+
io.puts "[##{slave_id}] slave #{slave_to_s(slave)} started (PID=#{slave.pid})"
|
|
102
|
+
end
|
|
103
|
+
manager.on_slave_finished do |slave|
|
|
104
|
+
slave, slave_id = deregister_slave_pid(slave.pid)
|
|
105
|
+
io.puts "[##{slave_id}] slave #{slave_to_s(slave)} finished (PID=#{slave.pid})"
|
|
106
|
+
end
|
|
107
|
+
server.on_exception do |pid, exception|
|
|
108
|
+
slave, slave_id = slave_from_pid(pid)
|
|
109
|
+
io.puts "[##{slave_id}] #{slave_to_s(slave)} reports exception"
|
|
110
|
+
Roby.display_exception(io, exception)
|
|
111
|
+
end
|
|
112
|
+
server.on_discovery_start do |pid|
|
|
113
|
+
slave, slave_id = slave_from_pid(pid)
|
|
114
|
+
io.puts "[##{slave_id}] #{slave_to_s(slave)} started discovery"
|
|
115
|
+
end
|
|
116
|
+
server.on_discovery_finished do |pid|
|
|
117
|
+
slave, slave_id = slave_from_pid(pid)
|
|
118
|
+
io.puts "[##{slave_id}] #{slave_to_s(slave)} finished discovery"
|
|
119
|
+
end
|
|
120
|
+
server.on_test_start do |pid|
|
|
121
|
+
slave, slave_id = slave_from_pid(pid)
|
|
122
|
+
io.puts "[##{slave_id}] #{slave_to_s(slave)} started testing"
|
|
123
|
+
end
|
|
124
|
+
server.on_test_result do |pid, file, test_case_name, test_name, failures, assertions, time|
|
|
125
|
+
slave, slave_id = slave_from_pid(pid)
|
|
126
|
+
io.puts "[##{slave_id}] #{test_case_name}##{test_name}: #{failures.size} failures and #{assertions.size} assertions (#{time})"
|
|
127
|
+
failures.each do |e|
|
|
128
|
+
Roby.display_exception(io, e)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
server.on_test_finished do |pid|
|
|
132
|
+
slave, slave_id = slave_from_pid(pid)
|
|
133
|
+
io.puts "[##{slave_id}] #{slave_to_s(slave)} finished testing"
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Roby
|
|
2
|
+
module App
|
|
3
|
+
DEFAULT_ROBOT_NAME = 'default'
|
|
4
|
+
DEFAULT_ROBOT_TYPE = 'default'
|
|
5
|
+
|
|
6
|
+
# Resolves the ROBOT keyword in the given path
|
|
7
|
+
#
|
|
8
|
+
# @param [String] path
|
|
9
|
+
# @param [String] robot_name
|
|
10
|
+
# @return [String]
|
|
11
|
+
def self.resolve_robot_in_path(path, robot_name = Roby.app.robot_name)
|
|
12
|
+
if robot_name == DEFAULT_ROBOT_NAME
|
|
13
|
+
robot_name = ""
|
|
14
|
+
end
|
|
15
|
+
robot_name ||= ""
|
|
16
|
+
|
|
17
|
+
path.gsub(/ROBOT/, robot_name).
|
|
18
|
+
gsub(/\/\//, '/')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
require 'roby/interface/async'
|
|
2
|
+
|
|
3
|
+
module Roby
|
|
4
|
+
module App
|
|
5
|
+
module Cucumber
|
|
6
|
+
# API that starts and communicates with a Roby controller for the
|
|
7
|
+
# benefit of a Cucumber scenario
|
|
8
|
+
class Controller
|
|
9
|
+
class InvalidState < RuntimeError; end
|
|
10
|
+
|
|
11
|
+
# The PID of the started Roby process
|
|
12
|
+
#
|
|
13
|
+
# @return [Integer,nil]
|
|
14
|
+
attr_reader :roby_pid
|
|
15
|
+
|
|
16
|
+
# The object used to communicate with the Roby instance
|
|
17
|
+
#
|
|
18
|
+
# It is set only after {#roby_wait} was called (or after a
|
|
19
|
+
# {#roby_start} whose wait parameter was set to true)
|
|
20
|
+
#
|
|
21
|
+
# @return [Roby::Interface::Client,nil]
|
|
22
|
+
attr_reader :roby_interface
|
|
23
|
+
|
|
24
|
+
# The set of jobs started by {#start_monitoring_job}
|
|
25
|
+
attr_reader :background_jobs
|
|
26
|
+
|
|
27
|
+
# The batch that gathers all the interface operations that will
|
|
28
|
+
# be executed at the next #run_job
|
|
29
|
+
attr_reader :current_batch
|
|
30
|
+
|
|
31
|
+
# Actions that would be started by {#current_batch}
|
|
32
|
+
attr_reader :pending_actions
|
|
33
|
+
|
|
34
|
+
# Whether the process should abort when an error is detected, or
|
|
35
|
+
# keep running the actions as-is. The latter is useful for
|
|
36
|
+
# debugging
|
|
37
|
+
#
|
|
38
|
+
# Active the keep running mode by setting CUCUMBER_KEEP_RUNNING
|
|
39
|
+
# to 1
|
|
40
|
+
attr_predicate :keep_running?, true
|
|
41
|
+
|
|
42
|
+
# Whether we run the jobs, or only validate their existence and
|
|
43
|
+
# arguments
|
|
44
|
+
#
|
|
45
|
+
# The validation mode is activated by setting
|
|
46
|
+
# ROBY_VALIDATE_STEPS to '1'
|
|
47
|
+
attr_predicate :validation_mode?, true
|
|
48
|
+
|
|
49
|
+
# Whether this started a Roby controller
|
|
50
|
+
def roby_running?
|
|
51
|
+
!!@roby_pid
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Whether we have a connection to the started Roby controller
|
|
55
|
+
def roby_connected?
|
|
56
|
+
roby_interface.connected?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def initialize(port: Roby::Interface::DEFAULT_PORT,
|
|
60
|
+
keep_running: (ENV['CUCUMBER_KEEP_RUNNING'] == '1'),
|
|
61
|
+
validation_mode: (ENV['ROBY_VALIDATE_STEPS'] == '1'))
|
|
62
|
+
@roby_pid = nil
|
|
63
|
+
@roby_interface = Roby::Interface::Async::Interface.
|
|
64
|
+
new('localhost', port: port)
|
|
65
|
+
@background_jobs = Array.new
|
|
66
|
+
@keep_running = keep_running
|
|
67
|
+
@validation_mode = validation_mode
|
|
68
|
+
@pending_actions = []
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Start a Roby controller
|
|
72
|
+
#
|
|
73
|
+
# @param [String] robot_name the name of the robot configuration
|
|
74
|
+
# @param [String] robot_type the type of the robot configuration
|
|
75
|
+
# @param [Boolean] wait whether the method should wait for a
|
|
76
|
+
# successful connection to the Roby application
|
|
77
|
+
# @param [Boolean] controller whether the configuration's controller
|
|
78
|
+
# blocks should be executed
|
|
79
|
+
# @param [Hash] state initial values for the state
|
|
80
|
+
#
|
|
81
|
+
# @raise InvalidState if a controller is already running
|
|
82
|
+
def roby_start(robot_name, robot_type, connect: true, controller: true, app_dir: Dir.pwd, log_dir: nil, state: Hash.new, **spawn_options)
|
|
83
|
+
if roby_running?
|
|
84
|
+
raise InvalidState, "a Roby controller is already running, call #roby_stop and #roby_join first"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
options = Array.new
|
|
88
|
+
if log_dir
|
|
89
|
+
options << "--log-dir=#{log_dir}"
|
|
90
|
+
end
|
|
91
|
+
@roby_pid = spawn Gem.ruby, File.join(Roby::BIN_DIR, "roby"), 'run',
|
|
92
|
+
"--robot=#{robot_name},#{robot_type}",
|
|
93
|
+
'--controller',
|
|
94
|
+
'--quiet',
|
|
95
|
+
*options,
|
|
96
|
+
*state.map { |k, v| "--set=#{k}=#{v}" },
|
|
97
|
+
chdir: app_dir,
|
|
98
|
+
pgroup: 0,
|
|
99
|
+
**spawn_options
|
|
100
|
+
if connect
|
|
101
|
+
roby_connect
|
|
102
|
+
end
|
|
103
|
+
roby_pid
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Try connecting to the Roby controller
|
|
107
|
+
#
|
|
108
|
+
# It sets {#roby_interface} on success
|
|
109
|
+
#
|
|
110
|
+
# @return [Roby::Interface::Client,nil] a valid interface object
|
|
111
|
+
# if the connection was successful, and nil otherwise
|
|
112
|
+
def roby_try_connect
|
|
113
|
+
if !roby_interface.connecting? && !roby_interface.connected?
|
|
114
|
+
roby_interface.attempt_connection
|
|
115
|
+
end
|
|
116
|
+
roby_interface.poll
|
|
117
|
+
roby_interface.connected?
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Wait for the Roby controller started with {#roby_start} to be
|
|
121
|
+
# available
|
|
122
|
+
def roby_connect
|
|
123
|
+
if roby_connected?
|
|
124
|
+
raise InvalidState, "already connected"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
while !roby_connected?
|
|
128
|
+
roby_try_connect
|
|
129
|
+
_, status = Process.waitpid2(roby_pid, Process::WNOHANG)
|
|
130
|
+
if status
|
|
131
|
+
raise InvalidState, "remote Roby controller quit before we could get a connection"
|
|
132
|
+
end
|
|
133
|
+
roby_interface.wait
|
|
134
|
+
end
|
|
135
|
+
@current_batch = @roby_interface.create_batch
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Disconnect the interface to the controller, but does not stop
|
|
139
|
+
# the controller
|
|
140
|
+
def roby_disconnect
|
|
141
|
+
if !roby_connected?
|
|
142
|
+
raise InvalidState, "not connected"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
@roby_interface.close
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Stops an already started Roby controller
|
|
149
|
+
#
|
|
150
|
+
# @raise InvalidState if no controllers were started
|
|
151
|
+
def roby_stop(join: true)
|
|
152
|
+
if !roby_running?
|
|
153
|
+
raise InvalidState, "cannot call #roby_stop if no controllers were started"
|
|
154
|
+
elsif !roby_connected?
|
|
155
|
+
raise InvalidState, "you need to successfully connect to the Roby controller with #roby_connect before you can call #roby_stop"
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
begin
|
|
159
|
+
roby_interface.quit
|
|
160
|
+
rescue Interface::ComError
|
|
161
|
+
ensure
|
|
162
|
+
roby_interface.close
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
roby_join if join
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Kill the Roby controller process
|
|
169
|
+
def roby_kill(join: true)
|
|
170
|
+
if !roby_running?
|
|
171
|
+
raise InvalidState, "cannot call #roby_stop if no controllers were started"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
Process.kill('INT', roby_pid)
|
|
175
|
+
roby_join if join
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
# Wait for the remote process to quit
|
|
180
|
+
def roby_join
|
|
181
|
+
if !roby_running?
|
|
182
|
+
raise InvalidState, "cannot call #roby_join without a running Roby controller"
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
_, status = Process.waitpid2(roby_pid)
|
|
186
|
+
@roby_pid = nil
|
|
187
|
+
status
|
|
188
|
+
rescue Errno::ECHILD
|
|
189
|
+
@roby_pid = nil
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Wait for the remote process to quit
|
|
193
|
+
#
|
|
194
|
+
# It raises an exception if the process does not terminate
|
|
195
|
+
# successfully
|
|
196
|
+
def roby_join!
|
|
197
|
+
if (status = roby_join) && !status.success?
|
|
198
|
+
raise InvalidState, "Roby process exited with status #{status}"
|
|
199
|
+
end
|
|
200
|
+
rescue Errno::ENOCHILD
|
|
201
|
+
@roby_pid = nil
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Enable or disable backtrace filtering on the Roby instance
|
|
205
|
+
def roby_enable_backtrace_filtering(enable: true)
|
|
206
|
+
if !roby_connected?
|
|
207
|
+
raise InvalidState, "you need to successfully connect to the Roby controller with #roby_connect before you can call #roby_enable_backtrace_filtering"
|
|
208
|
+
end
|
|
209
|
+
roby_interface.client.enable_backtrace_filtering(enable: enable)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# The log dir of the Roby app
|
|
213
|
+
#
|
|
214
|
+
# Since the roby app is local, this is a valid local path
|
|
215
|
+
def roby_log_dir
|
|
216
|
+
roby_interface.client.log_dir
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Exception raised when an monitor failed while an action was
|
|
220
|
+
# running
|
|
221
|
+
class FailedBackgroundJob < RuntimeError; end
|
|
222
|
+
|
|
223
|
+
# Exception raised when an action finished with any other state
|
|
224
|
+
# than 'success'
|
|
225
|
+
class FailedAction < RuntimeError; end
|
|
226
|
+
|
|
227
|
+
BackgroundJob = Struct.new :action_monitor, :description, :monitoring do
|
|
228
|
+
def job_id
|
|
229
|
+
action_monitor.job_id
|
|
230
|
+
end
|
|
231
|
+
def success?
|
|
232
|
+
action_monitor.success?
|
|
233
|
+
end
|
|
234
|
+
def terminated?
|
|
235
|
+
action_monitor.terminated?
|
|
236
|
+
end
|
|
237
|
+
def monitoring?
|
|
238
|
+
monitoring
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# The job ID of the last started
|
|
243
|
+
#
|
|
244
|
+
# @return [nil,Integer] nil if the job has not yet been started,
|
|
245
|
+
# and the ID otherwise. It's the caller responsibility to call
|
|
246
|
+
# {#apply_current_batch}
|
|
247
|
+
def last_main_job_id
|
|
248
|
+
if job = each_main_job.to_a.last
|
|
249
|
+
job.job_id
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# Start a job in the background
|
|
254
|
+
#
|
|
255
|
+
# Its failure will make the next #run_job step fail. Unlike a
|
|
256
|
+
# job created by {#start_monitoring_job}, it will not be stopped
|
|
257
|
+
# when {#run_job} is called.
|
|
258
|
+
def start_job(description, m, arguments = Hash.new)
|
|
259
|
+
if @has_run_job
|
|
260
|
+
drop_all_jobs if !validation_mode?
|
|
261
|
+
@has_run_job = false
|
|
262
|
+
end
|
|
263
|
+
__start_job(description, m, arguments, false)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# Start a background action whose failure will make the next
|
|
267
|
+
# #run_job step fail
|
|
268
|
+
#
|
|
269
|
+
# This action will be stopped at the end of the next {#run_job}
|
|
270
|
+
def start_monitoring_job(description, m, arguments = Hash.new)
|
|
271
|
+
__start_job(description, m, arguments, true)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# @api private
|
|
275
|
+
#
|
|
276
|
+
# Helper job-starting method
|
|
277
|
+
def __start_job(description, m, arguments, monitoring)
|
|
278
|
+
if validation_mode?
|
|
279
|
+
validate_job(m, arguments)
|
|
280
|
+
return
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
action = Interface::Async::ActionMonitor.new(roby_interface, m, arguments)
|
|
284
|
+
action.restart(batch: current_batch)
|
|
285
|
+
pending_actions << action
|
|
286
|
+
background_jobs << BackgroundJob.new(action, description, monitoring)
|
|
287
|
+
action
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# Enumerate all jobs started with {#start_monitoring_job}
|
|
291
|
+
def each_monitoring_job
|
|
292
|
+
return enum_for(__method__) if !block_given?
|
|
293
|
+
background_jobs.each do |job|
|
|
294
|
+
yield(job) if job.monitoring?
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# Enumerate all jobs started with {#start_job}
|
|
299
|
+
#
|
|
300
|
+
# These jobs are usually the job-under-test, hence the 'main'
|
|
301
|
+
# moniker
|
|
302
|
+
def each_main_job
|
|
303
|
+
return enum_for(__method__) if !block_given?
|
|
304
|
+
background_jobs.each do |job|
|
|
305
|
+
yield(job) if !job.monitoring?
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# Find one monitoring job that failed
|
|
310
|
+
def find_failed_monitoring_job
|
|
311
|
+
each_monitoring_job.find do |background_job|
|
|
312
|
+
background_job.terminated? && !background_job.success?
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# @api private
|
|
317
|
+
#
|
|
318
|
+
# Poll the interface until the block returns a truthy value
|
|
319
|
+
def roby_poll_interface_until
|
|
320
|
+
while !(result = yield)
|
|
321
|
+
if defined?(::Cucumber) && ::Cucumber.wants_to_quit
|
|
322
|
+
raise Interrupt, "Interrupted"
|
|
323
|
+
end
|
|
324
|
+
roby_interface.poll
|
|
325
|
+
roby_interface.wait
|
|
326
|
+
end
|
|
327
|
+
result
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def apply_current_batch(*actions, sync: true)
|
|
331
|
+
return if current_batch.empty?
|
|
332
|
+
|
|
333
|
+
batch_result = current_batch.__process
|
|
334
|
+
if sync
|
|
335
|
+
roby_poll_interface_until do
|
|
336
|
+
(pending_actions + actions).all? { |act| act.async }
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
batch_result
|
|
340
|
+
ensure
|
|
341
|
+
@current_batch = roby_interface.create_batch
|
|
342
|
+
@pending_actions = Array.new
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# Start an action
|
|
346
|
+
def run_job(m, arguments = Hash.new)
|
|
347
|
+
if validation_mode?
|
|
348
|
+
validate_job(m, arguments)
|
|
349
|
+
return
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
action = Interface::Async::ActionMonitor.new(roby_interface, m, arguments)
|
|
353
|
+
action.restart(batch: current_batch)
|
|
354
|
+
apply_current_batch(action)
|
|
355
|
+
@has_run_job = true
|
|
356
|
+
|
|
357
|
+
failed_monitor = roby_poll_interface_until do
|
|
358
|
+
if action.terminated?
|
|
359
|
+
break
|
|
360
|
+
else
|
|
361
|
+
find_failed_monitoring_job
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
if action.success?
|
|
366
|
+
return
|
|
367
|
+
elsif failed_monitor
|
|
368
|
+
if keep_running?
|
|
369
|
+
STDERR.puts
|
|
370
|
+
STDERR.puts "FAILED: monitoring job #{failed_monitor.description} failed"
|
|
371
|
+
STDERR.puts "In 'keep running' mode. Interrupt with CTRL+C"
|
|
372
|
+
roby_poll_interface_until { false }
|
|
373
|
+
else
|
|
374
|
+
raise FailedBackgroundJob, "monitoring job #{failed_monitor.description} failed"
|
|
375
|
+
end
|
|
376
|
+
else
|
|
377
|
+
if keep_running?
|
|
378
|
+
STDERR.puts
|
|
379
|
+
STDERR.puts "FAILED: action #{m} failed"
|
|
380
|
+
STDERR.puts "In 'keep running' mode. Interrupt with CTRL+C"
|
|
381
|
+
roby_poll_interface_until { false }
|
|
382
|
+
else
|
|
383
|
+
raise FailedAction, "action #{m} failed"
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
ensure
|
|
388
|
+
# Kill the monitoring actions as well as the main actions
|
|
389
|
+
drop_monitoring_jobs(*Array(action))
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
# Raised when validating the jobs
|
|
393
|
+
class InvalidJob < ArgumentError; end
|
|
394
|
+
|
|
395
|
+
# @api private
|
|
396
|
+
#
|
|
397
|
+
# Validate that the given action name and arguments match the
|
|
398
|
+
# interface's description
|
|
399
|
+
def validate_job(m, arguments)
|
|
400
|
+
if !(action = roby_interface.client.find_action_by_name(m))
|
|
401
|
+
raise InvalidJob, "no action is named '#{m}'"
|
|
402
|
+
end
|
|
403
|
+
arguments = arguments.dup
|
|
404
|
+
action.arguments.each do |arg|
|
|
405
|
+
arg_sym = arg.name.to_sym
|
|
406
|
+
has_arg = arguments.has_key?(arg_sym)
|
|
407
|
+
if !has_arg && arg.required?
|
|
408
|
+
raise InvalidJob, "#{m} requires an argument named #{arg.name} which is not provided"
|
|
409
|
+
end
|
|
410
|
+
arguments.delete(arg_sym)
|
|
411
|
+
end
|
|
412
|
+
if !arguments.empty?
|
|
413
|
+
raise InvalidJob, "arguments #{arguments.keys.map(&:to_s).sort.join(", ")} are not declared arguments of #{m}"
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
def drop_all_jobs(*extra_jobs)
|
|
418
|
+
jobs, @background_jobs =
|
|
419
|
+
background_jobs, Array.new
|
|
420
|
+
drop_jobs(*extra_jobs, *jobs.map(&:action_monitor))
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def drop_monitoring_jobs(*extra_jobs)
|
|
424
|
+
monitoring_jobs, @background_jobs =
|
|
425
|
+
background_jobs.partition { |j| j.monitoring? }
|
|
426
|
+
drop_jobs(*extra_jobs, *monitoring_jobs.map(&:action_monitor))
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
def drop_jobs(*jobs)
|
|
430
|
+
jobs.each do |act|
|
|
431
|
+
if !act.terminated? && act.async
|
|
432
|
+
act.drop(batch: current_batch)
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
end
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
end
|